2
0
Эх сурвалжийг харах

Merge pull request #13 from assimp/master

Update fork
Madrich 8 жил өмнө
parent
commit
ae0850b88c
95 өөрчлөгдсөн 5083 нэмэгдсэн , 908 устгасан
  1. 3 6
      .travis.yml
  2. 0 2
      CMakeLists.txt
  3. 8 8
      Readme.md
  4. 1 1
      code/3DSExporter.cpp
  5. 1 1
      code/AMFImporter_Postprocess.cpp
  6. 4 0
      code/ASELoader.cpp
  7. 4 3
      code/ASELoader.h
  8. 3 0
      code/ASEParser.cpp
  9. 4 0
      code/ASEParser.h
  10. 36 0
      code/AssbinExporter.cpp
  11. 37 0
      code/AssbinLoader.cpp
  12. 2 1
      code/AssimpCExport.cpp
  13. 0 5
      code/BaseImporter.cpp
  14. 1 4
      code/BlenderDNA.h
  15. 3 3
      code/BlenderModifier.cpp
  16. 6 1
      code/CMakeLists.txt
  17. 1 1
      code/ColladaExporter.cpp
  18. 5 7
      code/ColladaLoader.cpp
  19. 4 4
      code/ColladaParser.cpp
  20. 6 5
      code/Exporter.cpp
  21. 3 4
      code/FBXBinaryTokenizer.cpp
  22. 40 17
      code/FBXConverter.cpp
  23. 2 2
      code/FBXDocument.cpp
  24. 5 0
      code/FBXImportSettings.h
  25. 1 0
      code/FBXImporter.cpp
  26. 29 24
      code/FBXMaterial.cpp
  27. 1 1
      code/FBXMeshGeometry.cpp
  28. 12 0
      code/FBXParser.h
  29. 1818 0
      code/FIReader.cpp
  30. 172 0
      code/FIReader.hpp
  31. 2 3
      code/HalfLifeFileData.h
  32. 1 1
      code/IRRLoader.cpp
  33. 1 1
      code/IRRLoader.h
  34. 2 0
      code/ImporterRegistry.cpp
  35. 2 1
      code/LWOAnimation.cpp
  36. 3 4
      code/LWOAnimation.h
  37. 1 1
      code/LWSLoader.cpp
  38. 1 1
      code/LWSLoader.h
  39. 12 15
      code/MD3FileData.h
  40. 1 1
      code/MD3Loader.cpp
  41. 1 1
      code/MDCFileData.h
  42. 51 76
      code/MDLFileData.h
  43. 12 23
      code/ObjFileParser.cpp
  44. 4 4
      code/OgreParsingUtils.h
  45. 1 1
      code/OptimizeGraph.cpp
  46. 1 1
      code/OptimizeMeshes.cpp
  47. 3 0
      code/PlyLoader.cpp
  48. 5 24
      code/PlyParser.cpp
  49. 1 1
      code/PretransformVertices.cpp
  50. 1 1
      code/SceneCombiner.cpp
  51. 2 1
      code/StepExporter.cpp
  52. 1 1
      code/Subdivision.cpp
  53. 2 2
      code/X3DExporter.cpp
  54. 2 2
      code/X3DExporter.hpp
  55. 211 222
      code/X3DImporter.cpp
  56. 14 21
      code/X3DImporter.hpp
  57. 11 11
      code/X3DImporter_Geometry3D.cpp
  58. 8 8
      code/X3DImporter_Metadata.cpp
  59. 28 5
      code/X3DImporter_Networking.cpp
  60. 14 13
      code/X3DImporter_Node.hpp
  61. 117 22
      code/X3DImporter_Rendering.cpp
  62. 1675 0
      code/X3DVocabulary.cpp
  63. 2 1
      code/XFileExporter.cpp
  64. 2 1
      code/XFileImporter.cpp
  65. 4 7
      code/XFileParser.cpp
  66. 5 2
      code/glTFExporter.cpp
  67. 114 8
      contrib/openddlparser/CMakeLists.txt
  68. 3 0
      contrib/openddlparser/CREDITS
  69. 2 2
      contrib/openddlparser/README.md
  70. 14 6
      contrib/openddlparser/code/DDLNode.cpp
  71. 35 9
      contrib/openddlparser/code/OpenDDLCommon.cpp
  72. 1 55
      contrib/openddlparser/code/OpenDDLExport.cpp
  73. 80 65
      contrib/openddlparser/code/OpenDDLParser.cpp
  74. 96 0
      contrib/openddlparser/code/OpenDDLStream.cpp
  75. 17 18
      contrib/openddlparser/code/Value.cpp
  76. 19 10
      contrib/openddlparser/include/openddlparser/DDLNode.h
  77. 3 4
      contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
  78. 3 27
      contrib/openddlparser/include/openddlparser/OpenDDLExport.h
  79. 11 1
      contrib/openddlparser/include/openddlparser/OpenDDLParser.h
  80. 36 8
      contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
  81. 89 0
      contrib/openddlparser/include/openddlparser/OpenDDLStream.h
  82. 7 3
      contrib/openddlparser/include/openddlparser/Value.h
  83. 0 2
      include/assimp/SceneCombiner.h
  84. 10 3
      include/assimp/config.h.in
  85. 16 4
      include/assimp/material.inl
  86. 94 94
      port/PyAssimp/README.md
  87. 1 1
      port/PyAssimp/scripts/3d_viewer.py
  88. 1 1
      port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py
  89. 1 1
      port/PyAssimp/scripts/sample.py
  90. 2 2
      port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake
  91. 4 0
      test/unit/ut3DSImportExport.cpp
  92. 4 0
      test/unit/utASEImportExport.cpp
  93. 1 0
      test/unit/utBatchLoader.cpp
  94. 1 1
      test/unit/utObjTools.cpp
  95. 2 4
      test/unit/utglTFImportExport.cpp

+ 3 - 6
.travis.yml

@@ -2,7 +2,7 @@ sudo: required
 language: cpp
 language: cpp
 
 
 before_install:
 before_install:
-  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi
   - if [ "$TRAVIS_OS_NAME" =   "osx" ]; then brew install cmake python3 homebrew/x11/freeglut; fi
   - if [ "$TRAVIS_OS_NAME" =   "osx" ]; then brew install cmake python3 homebrew/x11/freeglut; fi
   - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
   - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
   # install latest LCOV (1.9 was failing)
   # install latest LCOV (1.9 was failing)
@@ -16,6 +16,7 @@ osx_image: xcode8.3
 
 
 env:
 env:
   global:
   global:
+  # COVERITY_SCAN_TOKEN
     - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
     - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
     - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
     - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
   matrix:
   matrix:
@@ -23,11 +24,7 @@ env:
     - LINUX=1 TRAVIS_NO_EXPORT=NO  ENABLE_COVERALLS=OFF
     - LINUX=1 TRAVIS_NO_EXPORT=NO  ENABLE_COVERALLS=OFF
     - LINUX=1 SHARED_BUILD=ON      ENABLE_COVERALLS=OFF
     - LINUX=1 SHARED_BUILD=ON      ENABLE_COVERALLS=OFF
     - LINUX=1 SHARED_BUILD=OFF     ENABLE_COVERALLS=OFF
     - LINUX=1 SHARED_BUILD=OFF     ENABLE_COVERALLS=OFF
-    #exclude:
-    #    - os: linux
-    #      compiler: clang
-    #    - os: osx
-    #      compiler: gcc  
+
 compiler:
 compiler:
   - gcc
   - gcc
   - clang
   - clang

+ 0 - 2
CMakeLists.txt

@@ -78,12 +78,10 @@ OPTION ( ASSIMP_COVERALLS
    "Eańable this to measure test coverage."
    "Eańable this to measure test coverage."
    OFF
    OFF
 )
 )
-
 option ( SYSTEM_IRRXML
 option ( SYSTEM_IRRXML
     "Use system installed Irrlicht/IrrXML library."
     "Use system installed Irrlicht/IrrXML library."
     OFF
     OFF
 )
 )
-
 OPTION ( BUILD_DOCS
 OPTION ( BUILD_DOCS
    "Build documentation using Doxygen."
    "Build documentation using Doxygen."
    OFF
    OFF

+ 8 - 8
Readme.md

@@ -1,6 +1,6 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ==================================
 ==================================
-
+### Current build status ###
 [![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
 [![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
 [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
 [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
 <a href="https://scan.coverity.com/projects/5607">
 <a href="https://scan.coverity.com/projects/5607">
@@ -9,22 +9,19 @@ Open Asset Import Library (assimp)
 </a>
 </a>
 <span class="badge-patreon"><a href="https://www.patreon.com/assimp" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
 <span class="badge-patreon"><a href="https://www.patreon.com/assimp" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
 [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
 [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
+[![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 <br>
 <br>
 
 
 APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
 APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
 
 
 Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
 Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
 
 
-This is the development trunk containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories.
-The current build status is:
-
-Gitter chat: [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
+This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
 
 
-And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type
-> /join #assetimporterlib
+One-off donations via PayPal:
+<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
 
 
 <br>
 <br>
-__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__
 
 
 Please check our Wiki as well: https://github.com/assimp/assimp/wiki
 Please check our Wiki as well: https://github.com/assimp/assimp/wiki
 
 
@@ -100,6 +97,9 @@ Take a look into the `INSTALL` file. Our build system is CMake, if you used CMak
 * [Pascal](port/AssimpPascal/Readme.md)
 * [Pascal](port/AssimpPascal/Readme.md)
 * [Javascript (Alpha)](https://github.com/makc/assimp2json)
 * [Javascript (Alpha)](https://github.com/makc/assimp2json)
 
 
+### Other tools ###
+[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
+
 #### Repository structure ####
 #### Repository structure ####
 Open Asset Import Library is implemented in C++. The directory structure is:
 Open Asset Import Library is implemented in C++. The directory structure is:
 
 

+ 1 - 1
code/3DSExporter.cpp

@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "3DSExporter.h"
 #include "3DSExporter.h"
 #include "3DSLoader.h"
 #include "3DSLoader.h"
 #include "3DSHelper.h"
 #include "3DSHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "SplitLargeMeshes.h"
 #include "SplitLargeMeshes.h"
 #include "StringComparison.h"
 #include "StringComparison.h"
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>

+ 1 - 1
code/AMFImporter_Postprocess.cpp

@@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AMFImporter.hpp"
 #include "AMFImporter.hpp"
 
 
 // Header files, Assimp.
 // Header files, Assimp.
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StandardShapes.h"
 #include "StandardShapes.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
 
 

+ 4 - 0
code/ASELoader.cpp

@@ -46,6 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 
 
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
+
 // internal headers
 // internal headers
 #include "ASELoader.h"
 #include "ASELoader.h"
 #include "StringComparison.h"
 #include "StringComparison.h"
@@ -1320,4 +1322,6 @@ bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)  {
     return false;
     return false;
 }
 }
 
 
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

+ 4 - 3
code/ASELoader.h

@@ -53,6 +53,7 @@ struct aiNode;
 
 
 namespace Assimp {
 namespace Assimp {
 
 
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 /** Importer class for the 3DS ASE ASCII format.
 /** Importer class for the 3DS ASE ASCII format.
@@ -63,9 +64,6 @@ public:
     ASEImporter();
     ASEImporter();
     ~ASEImporter();
     ~ASEImporter();
 
 
-
-public:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
     /** Returns whether the class can handle the format of the given file.
      * See BaseImporter::CanRead() for details.
      * See BaseImporter::CanRead() for details.
@@ -201,6 +199,9 @@ protected:
     bool noSkeletonMesh;
     bool noSkeletonMesh;
 };
 };
 
 
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 
+
 #endif // AI_3DSIMPORTER_H_INC
 #endif // AI_3DSIMPORTER_H_INC

+ 3 - 0
code/ASEParser.cpp

@@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 
 
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 
 // internal headers
 // internal headers
 #include "TextureTransform.h"
 #include "TextureTransform.h"
@@ -2151,4 +2152,6 @@ void Parser::ParseLV4MeshLong(unsigned int& iOut)
     iOut = strtoul10(filePtr,&filePtr);
     iOut = strtoul10(filePtr,&filePtr);
 }
 }
 
 
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

+ 4 - 0
code/ASEParser.h

@@ -49,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/mesh.h>
 #include <assimp/mesh.h>
 #include <assimp/anim.h>
 #include <assimp/anim.h>
 
 
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
+
 // for some helper routines like IsSpace()
 // for some helper routines like IsSpace()
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"
 #include "qnan.h"
 #include "qnan.h"
@@ -662,4 +664,6 @@ public:
 } // Namespace ASE
 } // Namespace ASE
 } // Namespace ASSIMP
 } // Namespace ASSIMP
 
 
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #endif // !! include guard
 #endif // !! include guard

+ 36 - 0
code/AssbinExporter.cpp

@@ -325,10 +325,13 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
         {
         {
             AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
             AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
 
 
+			size_t nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0);
+
             Write<aiString>(&chunk,node->mName);
             Write<aiString>(&chunk,node->mName);
             Write<aiMatrix4x4>(&chunk,node->mTransformation);
             Write<aiMatrix4x4>(&chunk,node->mTransformation);
             Write<unsigned int>(&chunk,node->mNumChildren);
             Write<unsigned int>(&chunk,node->mNumChildren);
             Write<unsigned int>(&chunk,node->mNumMeshes);
             Write<unsigned int>(&chunk,node->mNumMeshes);
+			Write<unsigned int>(&chunk,nb_metadata);
 
 
             for (unsigned int i = 0; i < node->mNumMeshes;++i) {
             for (unsigned int i = 0; i < node->mNumMeshes;++i) {
                 Write<unsigned int>(&chunk,node->mMeshes[i]);
                 Write<unsigned int>(&chunk,node->mMeshes[i]);
@@ -337,6 +340,39 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
             for (unsigned int i = 0; i < node->mNumChildren;++i) {
             for (unsigned int i = 0; i < node->mNumChildren;++i) {
                 WriteBinaryNode( &chunk, node->mChildren[i] );
                 WriteBinaryNode( &chunk, node->mChildren[i] );
             }
             }
+
+			for (unsigned int i = 0; i < nb_metadata; ++i) {
+				const aiString& key = node->mMetaData->mKeys[i];
+				aiMetadataType type = node->mMetaData->mValues[i].mType;
+				void* value = node->mMetaData->mValues[i].mData;
+
+				Write<aiString>(&chunk, key);
+				Write<uint16_t>(&chunk, type);
+				
+				switch (type) {
+				case AI_BOOL:
+					Write<bool>(&chunk, *((bool*) value));
+					break;
+				case AI_INT32:
+					Write<int32_t>(&chunk, *((int32_t*) value));
+					break;
+				case AI_UINT64:
+					Write<uint64_t>(&chunk, *((uint64_t*) value));
+					break;
+				case AI_FLOAT:
+					Write<float>(&chunk, *((float*) value));
+					break;
+				case AI_DOUBLE:
+					Write<double>(&chunk, *((double*) value));
+					break;
+				case AI_AISTRING:
+					Write<aiString>(&chunk, *((aiString*) value));
+					break;
+				case AI_AIVECTOR3D:
+					Write<aiVector3D>(&chunk, *((aiVector3D*) value));
+					break;
+				}
+			}
         }
         }
 
 
         // -----------------------------------------------------------------------------------
         // -----------------------------------------------------------------------------------

+ 37 - 0
code/AssbinLoader.cpp

@@ -210,6 +210,8 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* p
     (*node)->mTransformation = Read<aiMatrix4x4>(stream);
     (*node)->mTransformation = Read<aiMatrix4x4>(stream);
     (*node)->mNumChildren = Read<unsigned int>(stream);
     (*node)->mNumChildren = Read<unsigned int>(stream);
     (*node)->mNumMeshes = Read<unsigned int>(stream);
     (*node)->mNumMeshes = Read<unsigned int>(stream);
+	unsigned int nb_metadata = Read<unsigned int>(stream);
+
     if(parent)
     if(parent)
     {
     {
         (*node)->mParent = parent;
         (*node)->mParent = parent;
@@ -231,6 +233,41 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* p
         }
         }
     }
     }
 
 
+	if (nb_metadata)
+	{
+		(*node)->mMetaData = aiMetadata::Alloc(nb_metadata);
+		for (unsigned int i = 0; i < nb_metadata; ++i) {
+			(*node)->mMetaData->mKeys[i] = Read<aiString>(stream);
+			(*node)->mMetaData->mValues[i].mType = (aiMetadataType) Read<uint16_t>(stream);
+			void* data = NULL;
+
+			switch ((*node)->mMetaData->mValues[i].mType) {
+			case AI_BOOL:
+				data = new bool(Read<bool>(stream));
+				break;
+			case AI_INT32:
+				data = new int32_t(Read<int32_t>(stream));
+				break;
+			case AI_UINT64:
+				data = new uint64_t(Read<uint64_t>(stream));
+				break;
+			case AI_FLOAT:
+				data = new float(Read<float>(stream));
+				break;
+			case AI_DOUBLE:
+				data = new double(Read<double>(stream));
+				break;
+			case AI_AISTRING:
+				data = new aiString(Read<aiString>(stream));
+				break;
+			case AI_AIVECTOR3D:
+				data = new aiVector3D(Read<aiVector3D>(stream));
+				break;
+			}
+
+			(*node)->mMetaData->mValues[i].mData = data;
+		}
+	}
 }
 }
 
 
 // -----------------------------------------------------------------------------------
 // -----------------------------------------------------------------------------------

+ 2 - 1
code/AssimpCExport.cpp

@@ -45,8 +45,9 @@ Assimp C export interface. See Exporter.cpp for some notes.
 */
 */
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
+
 #include "CInterfaceIOWrapper.h"
 #include "CInterfaceIOWrapper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "ScenePrivate.h"
 #include "ScenePrivate.h"
 #include <assimp/Exporter.hpp>
 #include <assimp/Exporter.hpp>
 
 

+ 0 - 5
code/BaseImporter.cpp

@@ -337,7 +337,6 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
     if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
     if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
         DefaultLogger::get()->debug("Found UTF-32 BOM ...");
         DefaultLogger::get()->debug("Found UTF-32 BOM ...");
 
 
-        const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1;
         std::vector<char> output;
         std::vector<char> output;
         int *ptr = (int*)&data[ 0 ];
         int *ptr = (int*)&data[ 0 ];
         int *end = ptr + ( data.size() / sizeof(int) ) +1;
         int *end = ptr + ( data.size() / sizeof(int) ) +1;
@@ -358,11 +357,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
     if(*((uint16_t*)&data.front()) == 0xFEFF) {
     if(*((uint16_t*)&data.front()) == 0xFEFF) {
         DefaultLogger::get()->debug("Found UTF-16 BOM ...");
         DefaultLogger::get()->debug("Found UTF-16 BOM ...");
 
 
-        const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1);
         std::vector<unsigned char> output;
         std::vector<unsigned char> output;
-        int16_t *ptr = (int16_t*) &data[ 0 ];
-        int16_t *end = ptr + (data.size() / sizeof(int)) + 1;
-
         utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
         utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
         return;
         return;
     }
     }

+ 1 - 4
code/BlenderDNA.h

@@ -253,10 +253,7 @@ public:
      *  a compiler complain is the result.
      *  a compiler complain is the result.
      *  @param dest Destination value to be written
      *  @param dest Destination value to be written
      *  @param db File database, including input stream. */
      *  @param db File database, including input stream. */
-    template <typename T> inline void Convert (T& dest,
-        const FileDatabase& db) const;
-
-
+    template <typename T> inline void Convert (T& dest, const FileDatabase& db) const;
 
 
     // --------------------------------------------------------
     // --------------------------------------------------------
     // generic converter
     // generic converter

+ 3 - 3
code/BlenderModifier.cpp

@@ -43,10 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of some blender modifiers (i.e subdivision, mirror).
  *  @brief Implementation of some blender modifiers (i.e subdivision, mirror).
  */
  */
 
 
-
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
+
 #include "BlenderModifier.h"
 #include "BlenderModifier.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Subdivision.h"
 #include "Subdivision.h"
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <memory>
 #include <memory>
@@ -266,7 +266,7 @@ void  BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data,  co
 
 
     std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
     std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
     std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
     std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
-        std::bind1st(std::plus< unsigned int >(),out.mNumMeshes));
+        [&out](unsigned int n) { return out.mNumMeshes + n; });
 
 
     delete[] out.mMeshes;
     delete[] out.mMeshes;
     out.mMeshes = nind;
     out.mMeshes = nind;

+ 6 - 1
code/CMakeLists.txt

@@ -96,6 +96,7 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/Exporter.hpp
   ${HEADER_PATH}/Exporter.hpp
   ${HEADER_PATH}/DefaultIOStream.h
   ${HEADER_PATH}/DefaultIOStream.h
   ${HEADER_PATH}/DefaultIOSystem.h
   ${HEADER_PATH}/DefaultIOSystem.h
+  ${HEADER_PATH}/SceneCombiner.h
 )
 )
 
 
 SET( Core_SRCS
 SET( Core_SRCS
@@ -148,7 +149,6 @@ SET( Common_SRCS
   SpatialSort.cpp
   SpatialSort.cpp
   SpatialSort.h
   SpatialSort.h
   SceneCombiner.cpp
   SceneCombiner.cpp
-  SceneCombiner.h
   ScenePreprocessor.cpp
   ScenePreprocessor.cpp
   ScenePreprocessor.h
   ScenePreprocessor.h
   SkeletonMeshBuilder.cpp
   SkeletonMeshBuilder.cpp
@@ -647,6 +647,9 @@ ADD_ASSIMP_IMPORTER(X3D
   X3DImporter_Rendering.cpp
   X3DImporter_Rendering.cpp
   X3DImporter_Shape.cpp
   X3DImporter_Shape.cpp
   X3DImporter_Texturing.cpp
   X3DImporter_Texturing.cpp
+  FIReader.hpp
+  FIReader.cpp
+  X3DVocabulary.cpp
 )
 )
 
 
 ADD_ASSIMP_IMPORTER( GLTF
 ADD_ASSIMP_IMPORTER( GLTF
@@ -732,10 +735,12 @@ SET ( openddl_parser_SRCS
   ../contrib/openddlparser/code/OpenDDLCommon.cpp
   ../contrib/openddlparser/code/OpenDDLCommon.cpp
   ../contrib/openddlparser/code/OpenDDLExport.cpp
   ../contrib/openddlparser/code/OpenDDLExport.cpp
   ../contrib/openddlparser/code/Value.cpp
   ../contrib/openddlparser/code/Value.cpp
+  ../contrib/openddlparser/code/OpenDDLStream.cpp
   ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLExport.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLExport.h
+  ../contrib/openddlparser/include/openddlparser/OpenDDLStream.h
   ../contrib/openddlparser/include/openddlparser/DDLNode.h
   ../contrib/openddlparser/include/openddlparser/DDLNode.h
   ../contrib/openddlparser/include/openddlparser/Value.h
   ../contrib/openddlparser/include/openddlparser/Value.h
 )
 )

+ 1 - 1
code/ColladaExporter.cpp

@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ColladaExporter.h"
 #include "ColladaExporter.h"
 #include "Bitmap.h"
 #include "Bitmap.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StringUtils.h"
 #include "StringUtils.h"
 #include "XMLTools.h"
 #include "XMLTools.h"
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/DefaultIOSystem.h>

+ 5 - 7
code/ColladaLoader.cpp

@@ -132,7 +132,6 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Get file extension list
 // Get file extension list
 const aiImporterDesc* ColladaLoader::GetInfo () const
 const aiImporterDesc* ColladaLoader::GetInfo () const
@@ -1904,14 +1903,13 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-// Finds a proper name for a node derived from the collada-node's properties
+// Finds a proper unique name for a node derived from the collada-node's properties.
+// The name must be unique for proper node-bone association.
 std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
 std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
 {
 {
-    // now setup the name of the node. We take the name if not empty, otherwise the collada ID
-    // FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default.
-    if (!pNode->mName.empty() && pNode->mName != "untitled")
-        return pNode->mName;
-    else if (!pNode->mID.empty())
+    // Now setup the name of the assimp node. The collada name might not be
+    // unique, so we use the collada ID.
+    if (!pNode->mID.empty())
         return pNode->mID;
         return pNode->mID;
     else if (!pNode->mSID.empty())
     else if (!pNode->mSID.empty())
     return pNode->mSID;
     return pNode->mSID;

+ 4 - 4
code/ColladaParser.cpp

@@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the Collada parser helper
  *  @brief Implementation of the Collada parser helper
  */
  */
 
 
-
 #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
 #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
 
 
 #include <sstream>
 #include <sstream>
@@ -1866,7 +1865,7 @@ void ColladaParser::ReadMesh( Mesh* pMesh)
                 ReadIndexData( pMesh);
                 ReadIndexData( pMesh);
             } else
             } else
             {
             {
-                // ignore the rest
+                // ignore the restf
                 SkipElement();
                 SkipElement();
             }
             }
         }
         }
@@ -2216,8 +2215,9 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
             else if (IsElement("extra"))
             else if (IsElement("extra"))
             {
             {
                 SkipElement("extra");
                 SkipElement("extra");
-            } else
-            {
+            } else if ( IsElement("ph")) {                
+                SkipElement("ph");
+            } else {
                 ThrowException( format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">" );
                 ThrowException( format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">" );
             }
             }
         }
         }

+ 6 - 5
code/Exporter.cpp

@@ -54,7 +54,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 
 
 #include "BlobIOSystem.h"
 #include "BlobIOSystem.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "BaseProcess.h"
 #include "BaseProcess.h"
 #include "Importer.h" // need this for GetPostProcessingStepInstanceList()
 #include "Importer.h" // need this for GetPostProcessingStepInstanceList()
 
 
@@ -172,8 +172,10 @@ public:
         GetPostProcessingStepInstanceList(mPostProcessingSteps);
         GetPostProcessingStepInstanceList(mPostProcessingSteps);
 
 
         // grab all built-in exporters
         // grab all built-in exporters
-        mExporters.resize(ASSIMP_NUM_EXPORTERS);
-        std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
+        if ( 0 != ( ASSIMP_NUM_EXPORTERS ) ) {
+            mExporters.resize( ASSIMP_NUM_EXPORTERS );
+            std::copy( gExporters, gExporters + ASSIMP_NUM_EXPORTERS, mExporters.begin() );
+        }
     }
     }
 
 
     ~ExporterPimpl()
     ~ExporterPimpl()
@@ -187,7 +189,6 @@ public:
     }
     }
 
 
 public:
 public:
-
     aiExportDataBlob* blob;
     aiExportDataBlob* blob;
     std::shared_ptr< Assimp::IOSystem > mIOSystem;
     std::shared_ptr< Assimp::IOSystem > mIOSystem;
     bool mIsDefaultIOHandler;
     bool mIsDefaultIOHandler;
@@ -408,6 +409,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
 
 
     pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
     pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
+    
     return AI_FAILURE;
     return AI_FAILURE;
 }
 }
 
 
@@ -492,7 +494,6 @@ ExportProperties::ExportProperties(const ExportProperties &other)
     // empty
     // empty
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Set a configuration property
 // Set a configuration property
 bool ExportProperties::SetPropertyInteger(const char* szName, int iValue) {
 bool ExportProperties::SetPropertyInteger(const char* szName, int iValue) {

+ 3 - 4
code/FBXBinaryTokenizer.cpp

@@ -161,8 +161,7 @@ uint32_t ReadWord(const char* input, const char*& cursor, const char* end)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end)
-{
+uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) {
     const size_t k_to_read = sizeof(uint64_t);
     const size_t k_to_read = sizeof(uint64_t);
     if(Offset(cursor, end) < k_to_read) {
     if(Offset(cursor, end) < k_to_read) {
         TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor);
         TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor);
@@ -176,7 +175,6 @@ uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end)
     return dword;
     return dword;
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 uint8_t ReadByte(const char* input, const char*& cursor, const char* end)
 uint8_t ReadByte(const char* input, const char*& cursor, const char* end)
 {
 {
@@ -447,8 +445,9 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
     const uint32_t flags = ReadWord(input, cursor, input + length);
     const uint32_t flags = ReadWord(input, cursor, input + length);
 
 
     const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused
     const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused
+    (void) padding_0;
     const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused
     const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused
-
+    (void) padding_1;
     while (cursor < input + length)
     while (cursor < input + length)
     {
     {
         if(!ReadScope(output_tokens, input, cursor, input + length, flags)) {
         if(!ReadScope(output_tokens, input, cursor, input + length, flags)) {

+ 40 - 17
code/FBXConverter.cpp

@@ -436,6 +436,19 @@ private:
 
 
     aiScene* const out;
     aiScene* const out;
     const FBX::Document& doc;
     const FBX::Document& doc;
+
+	bool FindTextureIndexByFilename(const Video& video, unsigned int& index) {
+		index = 0;
+		const char* videoFileName = video.FileName().c_str();
+		for (auto texture = textures_converted.begin(); texture != textures_converted.end(); ++texture)
+		{
+			if (!strcmp(texture->first->FileName().c_str(), videoFileName)) {
+				return true;
+			}
+			index++;
+		}
+		return false;
+	}
 };
 };
 
 
 Converter::Converter( aiScene* out, const Document& doc )
 Converter::Converter( aiScene* out, const Document& doc )
@@ -1749,7 +1762,7 @@ unsigned int Converter::ConvertVideo( const Video& video )
     out_tex->mWidth = static_cast<unsigned int>( video.ContentLength() ); // total data size
     out_tex->mWidth = static_cast<unsigned int>( video.ContentLength() ); // total data size
     out_tex->mHeight = 0; // fixed to 0
     out_tex->mHeight = 0; // fixed to 0
 
 
-                            // steal the data from the Video to avoid an additional copy
+    // steal the data from the Video to avoid an additional copy
     out_tex->pcData = reinterpret_cast<aiTexel*>( const_cast<Video&>( video ).RelinquishContent() );
     out_tex->pcData = reinterpret_cast<aiTexel*>( const_cast<Video&>( video ).RelinquishContent() );
 
 
     // try to extract a hint from the file extension
     // try to extract a hint from the file extension
@@ -1783,22 +1796,32 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
         path.Set( tex->RelativeFilename() );
         path.Set( tex->RelativeFilename() );
 
 
         const Video* media = tex->Media();
         const Video* media = tex->Media();
-        if ( media != 0 && media->ContentLength() > 0 ) {
-            unsigned int index;
-
-            VideoMap::const_iterator it = textures_converted.find( media );
-            if ( it != textures_converted.end() ) {
-                index = ( *it ).second;
-            }
-            else {
-                index = ConvertVideo( *media );
-                textures_converted[ media ] = index;
-            }
-
-            // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
-            path.data[ 0 ] = '*';
-            path.length = 1 + ASSIMP_itoa10( path.data + 1, MAXLEN - 1, index );
-        }
+        if (media != 0) {
+			bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
+			unsigned int index;
+
+			VideoMap::const_iterator it = textures_converted.find(media);
+			if (it != textures_converted.end()) {
+				index = (*it).second;
+				textureReady = true;
+			}
+			else {
+				if (media->ContentLength() > 0) {
+					index = ConvertVideo(*media);
+					textures_converted[media] = index;
+					textureReady = true;
+				}
+				else if (doc.Settings().searchEmbeddedTextures) { //try to find the texture on the already-loaded textures by the filename, if the flag is on					
+					textureReady = FindTextureIndexByFilename(*media, index);
+				}
+			}
+
+			// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
+			if (textureReady) {
+				path.data[0] = '*';
+				path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+			}
+		}  
 
 
         out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
         out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
 
 

+ 2 - 2
code/FBXDocument.cpp

@@ -565,7 +565,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id,
         temp.push_back((*it).second);
         temp.push_back((*it).second);
     }
     }
 
 
-    std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare));
+    std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
 
 
     return temp; // NRVO should handle this
     return temp; // NRVO should handle this
 }
 }
@@ -617,7 +617,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
         temp.push_back((*it).second);
         temp.push_back((*it).second);
     }
     }
 
 
-    std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare));
+    std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
     return temp; // NRVO should handle this
     return temp; // NRVO should handle this
 }
 }
 
 

+ 5 - 0
code/FBXImportSettings.h

@@ -63,6 +63,7 @@ struct ImportSettings
         , readWeights(true)
         , readWeights(true)
         , preservePivots(true)
         , preservePivots(true)
         , optimizeEmptyAnimationCurves(true)
         , optimizeEmptyAnimationCurves(true)
+		, searchEmbeddedTextures(false)
     {}
     {}
 
 
 
 
@@ -137,6 +138,10 @@ struct ImportSettings
      *  values matching the corresponding node transformation.
      *  values matching the corresponding node transformation.
      *  The default value is true. */
      *  The default value is true. */
     bool optimizeEmptyAnimationCurves;
     bool optimizeEmptyAnimationCurves;
+
+	/** search for embedded loaded textures, where no embedded texture data is provided.
+	*  The default value is false. */
+	bool searchEmbeddedTextures;
 };
 };
 
 
 
 

+ 1 - 0
code/FBXImporter.cpp

@@ -131,6 +131,7 @@ void FBXImporter::SetupProperties(const Importer* pImp)
     settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
     settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
     settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
     settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
     settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
     settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
+	settings.searchEmbeddedTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES, false);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 29 - 24
code/FBXMaterial.cpp

@@ -281,7 +281,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
     const Scope& sc = GetRequiredScope(element);
     const Scope& sc = GetRequiredScope(element);
 
 
     const Element* const Type = sc["Type"];
     const Element* const Type = sc["Type"];
-    const Element* const FileName = sc["FileName"];
+    const Element* const FileName = sc.FindElementCaseInsensitive("FileName");  //some files retain the information as "Filename", others "FileName", who knows
     const Element* const RelativeFilename = sc["RelativeFilename"];
     const Element* const RelativeFilename = sc["RelativeFilename"];
     const Element* const Content = sc["Content"];
     const Element* const Content = sc["Content"];
 
 
@@ -291,35 +291,40 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
 
 
     if(FileName) {
     if(FileName) {
         fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
         fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
-    }
+	}
 
 
     if(RelativeFilename) {
     if(RelativeFilename) {
         relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
         relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
     }
     }
 
 
     if(Content) {
     if(Content) {
-        const Token& token = GetRequiredToken(*Content, 0);
-        const char* data = token.begin();
-        if(!token.IsBinary()) {
-            DOMWarning("video content is not binary data, ignoring", &element);
-        }
-        else if(static_cast<size_t>(token.end() - data) < 5) {
-            DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
-        }
-        else if(*data != 'R') {
-            DOMWarning("video content is not raw binary data, ignoring", &element);
-        }
-        else {
-            // read number of elements
-            uint32_t len = 0;
-            ::memcpy(&len, data + 1, sizeof(len));
-            AI_SWAP4(len);
-
-            contentLength = len;
-
-            content = new uint8_t[len];
-            ::memcpy(content, data + 5, len);
-        }
+		//this field is ommited when the embedded texture is already loaded, let's ignore if it´s not found
+		try {
+			const Token& token = GetRequiredToken(*Content, 0);
+			const char* data = token.begin();
+			if (!token.IsBinary()) {
+				DOMWarning("video content is not binary data, ignoring", &element);
+			}
+			else if (static_cast<size_t>(token.end() - data) < 5) {
+				DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
+			}
+			else if (*data != 'R') {
+				DOMWarning("video content is not raw binary data, ignoring", &element);
+			}
+			else {
+				// read number of elements
+				uint32_t len = 0;
+				::memcpy(&len, data + 1, sizeof(len));
+				AI_SWAP4(len);
+
+				contentLength = len;
+
+				content = new uint8_t[len];
+				::memcpy(content, data + 5, len);
+			}
+		} catch (runtime_error runtimeError) {
+			//we don´t need the content data for contents that has already been loaded
+		}
     }
     }
 
 
     props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
     props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);

+ 1 - 1
code/FBXMeshGeometry.cpp

@@ -357,7 +357,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
         // avoids losing the material if there are more material layers
         // avoids losing the material if there are more material layers
         // coming of which at least one contains actual data (did observe
         // coming of which at least one contains actual data (did observe
         // that with one test file).
         // that with one test file).
-        const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),std::bind2nd(std::less<int>(),0));
+        const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),[](int n) { return n < 0; });
         if(count_neg == temp_materials.size()) {
         if(count_neg == temp_materials.size()) {
             FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
             FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
             return;
             return;

+ 12 - 0
code/FBXParser.h

@@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <map>
 #include <map>
 #include <memory>
 #include <memory>
 #include "LogAux.h"
 #include "LogAux.h"
+#include "fast_atof.h"
 
 
 #include "FBXCompileConfig.h"
 #include "FBXCompileConfig.h"
 #include "FBXTokenizer.h"
 #include "FBXTokenizer.h"
@@ -137,6 +138,17 @@ public:
         return it == elements.end() ? NULL : (*it).second;
         return it == elements.end() ? NULL : (*it).second;
     }
     }
 
 
+	const Element* FindElementCaseInsensitive(const std::string& elementName) const {
+		const char* elementNameCStr = elementName.c_str();
+		for (auto element = elements.begin(); element != elements.end(); ++element)
+		{
+			if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
+				return element->second;
+			}
+		}
+		return NULL;
+	}
+
     ElementCollection GetCollection(const std::string& index) const {
     ElementCollection GetCollection(const std::string& index) const {
         return elements.equal_range(index);
         return elements.equal_range(index);
     }
     }

+ 1818 - 0
code/FIReader.cpp

@@ -0,0 +1,1818 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/// \file   FIReader.cpp
+/// \brief  Reader for Fast Infoset encoded binary XML files.
+/// \date   2017
+/// \author Patrick Daehne
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "FIReader.hpp"
+#include "Exceptional.h"
+#include <assimp/IOStream.hpp>
+#include <assimp/types.h>
+#include "MemoryIOWrapper.h"
+#include "irrXMLWrapper.h"
+#include "../contrib/utf8cpp/source/utf8.h"
+#include <stack>
+#include <map>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+namespace Assimp {
+
+static const std::string parseErrorMessage = "Fast Infoset parse error";
+
+static const char *xmlDeclarations[] = {
+    "<?xml encoding='finf'?>",
+    "<?xml encoding='finf' standalone='yes'?>",
+    "<?xml encoding='finf' standalone='no'?>",
+    "<?xml version='1.0' encoding='finf'?>",
+    "<?xml version='1.0' encoding='finf' standalone='yes'?>",
+    "<?xml version='1.0' encoding='finf' standalone='no'?>",
+    "<?xml version='1.1' encoding='finf'?>",
+    "<?xml version='1.1' encoding='finf' standalone='yes'?>",
+    "<?xml version='1.1' encoding='finf' standalone='no'?>"
+};
+
+static size_t parseMagic(const uint8_t *data, const uint8_t *dataEnd) {
+    if (dataEnd - data < 4) {
+        return 0;
+    }
+    uint32_t magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+    switch (magic) {
+    case 0xe0000001:
+        return 4;
+    case 0x3c3f786d: // "<?xm"
+        {
+            size_t xmlDeclarationsLength = sizeof(xmlDeclarations) / sizeof(xmlDeclarations[0]);
+            for (size_t i = 0; i < xmlDeclarationsLength; ++i) {
+                auto xmlDeclaration = xmlDeclarations[i];
+                ptrdiff_t xmlDeclarationLength = strlen(xmlDeclaration);
+                if ((dataEnd - data >= xmlDeclarationLength) && (memcmp(xmlDeclaration, data, xmlDeclarationLength) == 0)) {
+                    data += xmlDeclarationLength;
+                    if (dataEnd - data < 4) {
+                        return 0;
+                    }
+                    magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+                    return magic == 0xe0000001 ? xmlDeclarationLength + 4 : 0;
+                }
+            }
+            return 0;
+        }
+    default:
+        return 0;
+    }
+}
+
+static std::string parseUTF8String(const uint8_t *data, size_t len) {
+    return std::string((char*)data, len);
+}
+
+static std::string parseUTF16String(const uint8_t *data, size_t len) {
+    if (len & 1) {
+        throw DeadlyImportError(parseErrorMessage);
+    }
+    size_t numShorts = len / 2;
+    std::vector<short> utf16;
+    utf16.reserve(numShorts);
+    for (size_t i = 0; i < numShorts; ++i) {
+        short v = (data[0] << 8) | data[1];
+        utf16.push_back(v);
+        data += 2;
+    }
+    std::string result;
+    utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(result));
+    return result;
+}
+
+struct FIStringValueImpl: public FIStringValue {
+    inline FIStringValueImpl(std::string &&value_) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ { return value; }
+};
+
+std::shared_ptr<FIStringValue> FIStringValue::create(std::string &&value) {
+    return std::make_shared<FIStringValueImpl>(std::move(value));
+}
+
+struct FIHexValueImpl: public FIHexValue {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FIHexValueImpl(std::vector<uint8_t> &&value_):  strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            os << std::hex << std::uppercase << std::setfill('0');
+            std::for_each(value.begin(), value.end(), [&](uint8_t c) { os << std::setw(2) << static_cast<int>(c); });
+            strValue = os.str();
+        }
+        return strValue;
+    };
+};
+
+std::shared_ptr<FIHexValue> FIHexValue::create(std::vector<uint8_t> &&value) {
+    return std::make_shared<FIHexValueImpl>(std::move(value));
+}
+
+struct FIBase64ValueImpl: public FIBase64Value {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FIBase64ValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            uint8_t c1, c2;
+            int imod3 = 0;
+            std::vector<uint8_t>::size_type valueSize = value.size();
+            for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
+                c2 = value[i];
+                switch (imod3) {
+                case 0:
+                    os << basis_64[c2 >> 2];
+                    imod3 = 1;
+                    break;
+                case 1:
+                    os << basis_64[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
+                    imod3 = 2;
+                    break;
+                case 2:
+                    os << basis_64[((c1 & 0x0f) << 2) | ((c2 & 0xc0) >> 6)] << basis_64[c2 & 0x3f];
+                    imod3 = 0;
+                    break;
+                }
+                c1 = c2;
+            }
+            switch (imod3) {
+            case 1:
+                os << basis_64[(c1 & 0x03) << 4] << "==";
+                break;
+            case 2:
+                os << basis_64[(c1 & 0x0f) << 2] << '=';
+                break;
+            }
+            strValue = os.str();
+        }
+        return strValue;
+    };
+    static const char basis_64[];
+};
+
+const char FIBase64ValueImpl::basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+std::shared_ptr<FIBase64Value> FIBase64Value::create(std::vector<uint8_t> &&value) {
+    return std::make_shared<FIBase64ValueImpl>(std::move(value));
+}
+
+struct FIShortValueImpl: public FIShortValue {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FIShortValueImpl(std::vector<int16_t> &&value_): strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            int n = 0;
+            std::for_each(value.begin(), value.end(), [&](int16_t s) { if (++n > 1) os << ' '; os << s; });
+            strValue = os.str();
+        }
+        return strValue;
+    }
+};
+
+std::shared_ptr<FIShortValue> FIShortValue::create(std::vector<int16_t> &&value) {
+    return std::make_shared<FIShortValueImpl>(std::move(value));
+}
+
+struct FIIntValueImpl: public FIIntValue {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FIIntValueImpl(std::vector<int32_t> &&value_): strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            int n = 0;
+            std::for_each(value.begin(), value.end(), [&](int32_t i) { if (++n > 1) os << ' '; os << i; });
+            strValue = os.str();
+        }
+        return strValue;
+    };
+};
+
+std::shared_ptr<FIIntValue> FIIntValue::create(std::vector<int32_t> &&value) {
+    return std::make_shared<FIIntValueImpl>(std::move(value));
+}
+
+struct FILongValueImpl: public FILongValue {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FILongValueImpl(std::vector<int64_t> &&value_): strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            int n = 0;
+            std::for_each(value.begin(), value.end(), [&](int64_t l) { if (++n > 1) os << ' '; os << l; });
+            strValue = os.str();
+        }
+        return strValue;
+    };
+};
+
+std::shared_ptr<FILongValue> FILongValue::create(std::vector<int64_t> &&value) {
+    return std::make_shared<FILongValueImpl>(std::move(value));
+}
+
+struct FIBoolValueImpl: public FIBoolValue {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FIBoolValueImpl(std::vector<bool> &&value_): strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            os << std::boolalpha;
+            int n = 0;
+            std::for_each(value.begin(), value.end(), [&](bool b) { if (++n > 1) os << ' '; os << b; });
+            strValue = os.str();
+        }
+        return strValue;
+    };
+};
+
+std::shared_ptr<FIBoolValue> FIBoolValue::create(std::vector<bool> &&value) {
+    return std::make_shared<FIBoolValueImpl>(std::move(value));
+}
+
+struct FIFloatValueImpl: public FIFloatValue {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FIFloatValueImpl(std::vector<float> &&value_): strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            int n = 0;
+            std::for_each(value.begin(), value.end(), [&](float f) { if (++n > 1) os << ' '; os << f; });
+            strValue = os.str();
+        }
+        return strValue;
+    }
+};
+
+std::shared_ptr<FIFloatValue> FIFloatValue::create(std::vector<float> &&value) {
+    return std::make_shared<FIFloatValueImpl>(std::move(value));
+}
+
+struct FIDoubleValueImpl: public FIDoubleValue {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FIDoubleValueImpl(std::vector<double> &&value_): strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            int n = 0;
+            std::for_each(value.begin(), value.end(), [&](double d) { if (++n > 1) os << ' '; os << d; });
+            strValue = os.str();
+        }
+        return strValue;
+    }
+};
+
+std::shared_ptr<FIDoubleValue> FIDoubleValue::create(std::vector<double> &&value) {
+    return std::make_shared<FIDoubleValueImpl>(std::move(value));
+}
+
+struct FIUUIDValueImpl: public FIUUIDValue {
+    mutable std::string strValue;
+    mutable bool strValueValid;
+    inline FIUUIDValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ {
+        if (!strValueValid) {
+            strValueValid = true;
+            std::ostringstream os;
+            os << std::hex << std::uppercase << std::setfill('0');
+            std::vector<uint8_t>::size_type valueSize = value.size();
+            for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
+                switch (i & 15) {
+                case 0:
+                    if (i > 0) {
+                        os << ' ';
+                    }
+                    os << std::setw(2) << static_cast<int>(value[i]);
+                    break;
+                case 4:
+                case 6:
+                case 8:
+                case 10:
+                    os << '-';
+                    // intentionally fall through!
+                case 1:
+                case 2:
+                case 3:
+                case 5:
+                case 7:
+                case 9:
+                case 11:
+                case 12:
+                case 13:
+                case 14:
+                case 15:
+                    os << std::setw(2) << static_cast<int>(value[i]);
+                    break;
+                }
+            }
+            strValue = os.str();
+        }
+        return strValue;
+    };
+};
+
+std::shared_ptr<FIUUIDValue> FIUUIDValue::create(std::vector<uint8_t> &&value) {
+    return std::make_shared<FIUUIDValueImpl>(std::move(value));
+}
+
+struct FICDATAValueImpl: public FICDATAValue {
+    inline FICDATAValueImpl(std::string &&value_) { value = std::move(value_); }
+    virtual const std::string &toString() const /*override*/ { return value; }
+};
+
+std::shared_ptr<FICDATAValue> FICDATAValue::create(std::string &&value) {
+    return std::make_shared<FICDATAValueImpl>(std::move(value));
+}
+
+struct FIHexDecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        return FIHexValue::create(std::vector<uint8_t>(data, data + len));
+    }
+};
+
+struct FIBase64Decoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        return FIBase64Value::create(std::vector<uint8_t>(data, data + len));
+    }
+};
+
+struct FIShortDecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        if (len & 1) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        std::vector<int16_t> value;
+        size_t numShorts = len / 2;
+        value.reserve(numShorts);
+        for (size_t i = 0; i < numShorts; ++i) {
+            int16_t v = (data[0] << 8) | data[1];
+            value.push_back(v);
+            data += 2;
+        }
+        return FIShortValue::create(std::move(value));
+    }
+};
+
+struct FIIntDecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        if (len & 3) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        std::vector<int32_t> value;
+        size_t numInts = len / 4;
+        value.reserve(numInts);
+        for (size_t i = 0; i < numInts; ++i) {
+            int32_t v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+            value.push_back(v);
+            data += 4;
+        }
+        return FIIntValue::create(std::move(value));
+    }
+};
+
+struct FILongDecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        if (len & 7) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        std::vector<int64_t> value;
+        size_t numLongs = len / 8;
+        value.reserve(numLongs);
+        for (size_t i = 0; i < numLongs; ++i) {
+            int64_t b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
+            int64_t v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+            value.push_back(v);
+            data += 8;
+        }
+        return FILongValue::create(std::move(value));
+    }
+};
+
+struct FIBoolDecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        if (len < 1) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        std::vector<bool> value;
+        uint8_t b = *data++;
+        size_t unusedBits = b >> 4;
+        size_t numBools = (len * 8) - 4 - unusedBits;
+        value.reserve(numBools);
+        uint8_t mask = 1 << 3;
+        for (size_t i = 0; i < numBools; ++i) {
+            if (!mask) {
+                mask = 1 << 7;
+                b = *data++;
+            }
+            value.push_back((b & mask) != 0);
+        }
+        return FIBoolValue::create(std::move(value));
+    }
+};
+
+struct FIFloatDecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        if (len & 3) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        std::vector<float> value;
+        size_t numFloats = len / 4;
+        value.reserve(numFloats);
+        for (size_t i = 0; i < numFloats; ++i) {
+            int v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+            value.push_back(*(float*)&v);
+            data += 4;
+        }
+        return FIFloatValue::create(std::move(value));
+    }
+};
+
+struct FIDoubleDecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        if (len & 7) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        std::vector<double> value;
+        size_t numDoubles = len / 8;
+        value.reserve(numDoubles);
+        for (size_t i = 0; i < numDoubles; ++i) {
+            long long b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
+            long long v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+            value.push_back(*(double*)&v);
+            data += 8;
+        }
+        return FIDoubleValue::create(std::move(value));
+    }
+};
+
+struct FIUUIDDecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        if (len & 15) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        return FIUUIDValue::create(std::vector<uint8_t>(data, data + len));
+    }
+};
+
+struct FICDATADecoder: public FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+        return FICDATAValue::create(parseUTF8String(data, len));
+    }
+};
+
+class CFIReaderImpl: public FIReader {
+public:
+
+    CFIReaderImpl(std::unique_ptr<uint8_t[]> data_, size_t size):
+    data(std::move(data_)), dataP(data.get()), dataEnd(data.get() + size), currentNodeType(irr::io::EXN_NONE),
+    emptyElement(false), headerPending(true), terminatorPending(false)
+    {}
+
+    virtual ~CFIReaderImpl() {}
+
+    virtual bool read() /*override*/ {
+        if (headerPending) {
+            headerPending = false;
+            parseHeader();
+        }
+        if (terminatorPending) {
+            terminatorPending = false;
+            if (elementStack.empty()) {
+                return false;
+            }
+            else {
+                nodeName = elementStack.top();
+                elementStack.pop();
+                currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
+                return true;
+            }
+        }
+        if (dataP >= dataEnd) {
+            return false;
+        }
+        uint8_t b = *dataP;
+        if (b < 0x80) { // Element (C.2.11.2, C.3.7.2)
+            // C.3
+            parseElement();
+            return true;
+        }
+        else if (b < 0xc0) { // Characters (C.3.7.5)
+            // C.7
+            auto chars = parseNonIdentifyingStringOrIndex3(vocabulary.charactersTable);
+            nodeName = chars->toString();
+            currentNodeType = irr::io::EXN_TEXT;
+            return true;
+        }
+        else if (b < 0xe0) {
+            if ((b & 0xfc) == 0xc4) { // DTD (C.2.11.5)
+                // C.9
+                ++dataP;
+                if (b & 0x02) {
+                    /*const std::string &systemID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+                }
+                if (b & 0x01) {
+                    /*const std::string &publicID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+                }
+                elementStack.push(EmptyString);
+                currentNodeType = irr::io::EXN_UNKNOWN;
+                return true;
+            }
+            else if ((b & 0xfc) == 0xc8) { // Unexpanded entity reference (C.3.7.4)
+                // C.6
+                ++dataP;
+                /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+                if (b & 0x02) {
+                    /*const std::string &systemID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+                }
+                if (b & 0x01) {
+                    /*const std::string &publicID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+                }
+                currentNodeType = irr::io::EXN_UNKNOWN;
+                return true;
+            }
+        }
+        else if (b < 0xf0) {
+            if (b == 0xe1) { // Processing instruction (C.2.11.3, C.3.7.3)
+                // C.5
+                ++dataP;
+                /*const std::string &target =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                /*std::shared_ptr<const FIValue> data =*/ parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+                currentNodeType = irr::io::EXN_UNKNOWN;
+                return true;
+            }
+            else if (b == 0xe2) { // Comment (C.2.11.4, C.3.7.6)
+                // C.8
+                ++dataP;
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                std::shared_ptr<const FIValue> comment = parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+                nodeName = comment->toString();
+                currentNodeType = irr::io::EXN_COMMENT;
+                return true;
+            }
+        }
+        else { // Terminator (C.2.12, C.3.8)
+            ++dataP;
+            if (b == 0xff) {
+                terminatorPending = true;
+            }
+            if (elementStack.empty()) {
+                return false;
+            }
+            else {
+                nodeName = elementStack.top();
+                elementStack.pop();
+                currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
+                return true;
+            }
+        }
+        throw DeadlyImportError(parseErrorMessage);
+    }
+
+    virtual irr::io::EXML_NODE getNodeType() const /*override*/ {
+        return currentNodeType;
+    }
+
+    virtual int getAttributeCount() const /*override*/ {
+        return static_cast<int>(attributes.size());
+    }
+
+    virtual const char* getAttributeName(int idx) const /*override*/ {
+        if (idx < 0 || idx >= (int)attributes.size()) {
+            return nullptr;
+        }
+        return attributes[idx].name.c_str();
+    }
+
+    virtual const char* getAttributeValue(int idx) const /*override*/ {
+        if (idx < 0 || idx >= (int)attributes.size()) {
+            return nullptr;
+        }
+        return attributes[idx].value->toString().c_str();
+    }
+
+    virtual const char* getAttributeValue(const char* name) const /*override*/ {
+        const Attribute* attr = getAttributeByName(name);
+        if (!attr) {
+            return nullptr;
+        }
+        return attr->value->toString().c_str();
+    }
+
+    virtual const char* getAttributeValueSafe(const char* name) const /*override*/ {
+        const Attribute* attr = getAttributeByName(name);
+        if (!attr) {
+            return EmptyString.c_str();
+        }
+        return attr->value->toString().c_str();
+    }
+
+    virtual int getAttributeValueAsInt(const char* name) const /*override*/ {
+        const Attribute* attr = getAttributeByName(name);
+        if (!attr) {
+            return 0;
+        }
+        std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attr->value);
+        if (intValue) {
+            return intValue->value.size() == 1 ? intValue->value.front() : 0;
+        }
+        return stoi(attr->value->toString());
+    }
+
+    virtual int getAttributeValueAsInt(int idx) const /*override*/ {
+        if (idx < 0 || idx >= (int)attributes.size()) {
+            return 0;
+        }
+        std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attributes[idx].value);
+        if (intValue) {
+            return intValue->value.size() == 1 ? intValue->value.front() : 0;
+        }
+        return stoi(attributes[idx].value->toString());
+    }
+
+    virtual float getAttributeValueAsFloat(const char* name) const /*override*/ {
+        const Attribute* attr = getAttributeByName(name);
+        if (!attr) {
+            return 0;
+        }
+        std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attr->value);
+        if (floatValue) {
+            return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
+        }
+        return stof(attr->value->toString());
+    }
+
+    virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
+        if (idx < 0 || idx >= (int)attributes.size()) {
+            return 0;
+        }
+        std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attributes[idx].value);
+        if (floatValue) {
+            return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
+        }
+        return stof(attributes[idx].value->toString());
+    }
+
+    virtual const char* getNodeName() const /*override*/ {
+        return nodeName.c_str();
+    }
+
+    virtual const char* getNodeData() const /*override*/ {
+        return nodeName.c_str();
+    }
+
+    virtual bool isEmptyElement() const /*override*/ {
+        return emptyElement;
+    }
+
+    virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ {
+        return irr::io::ETF_UTF8;
+    }
+
+    virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ {
+        return irr::io::ETF_UTF8;
+    }
+
+    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const /*override*/ {
+        if (idx < 0 || idx >= (int)attributes.size()) {
+            return nullptr;
+        }
+        return attributes[idx].value;
+    }
+
+    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char* name) const /*override*/ {
+        const Attribute* attr = getAttributeByName(name);
+        if (!attr) {
+            return nullptr;
+        }
+        return attr->value;
+    }
+
+    virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) /*override*/ {
+        decoderMap[algorithmUri] = std::move(decoder);
+    }
+
+    virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) /*override*/ {
+        vocabularyMap[vocabularyUri] = vocabulary;
+    }
+
+private:
+
+    struct QName {
+        std::string prefix;
+        std::string uri;
+        std::string name;
+        inline QName() {}
+        inline QName(const FIQName &qname): prefix(qname.prefix ? qname.prefix : ""), uri(qname.uri ? qname.uri : ""), name(qname.name) {}
+    };
+
+    struct Attribute {
+        QName qname;
+        std::string name;
+        std::shared_ptr<const FIValue> value;
+    };
+
+    struct Vocabulary {
+        std::vector<std::string> restrictedAlphabetTable;
+        std::vector<std::string> encodingAlgorithmTable;
+        std::vector<std::string> prefixTable;
+        std::vector<std::string> namespaceNameTable;
+        std::vector<std::string> localNameTable;
+        std::vector<std::string> otherNCNameTable;
+        std::vector<std::string> otherURITable;
+        std::vector<std::shared_ptr<const FIValue>> attributeValueTable;
+        std::vector<std::shared_ptr<const FIValue>> charactersTable;
+        std::vector<std::shared_ptr<const FIValue>> otherStringTable;
+        std::vector<QName> elementNameTable;
+        std::vector<QName> attributeNameTable;
+        Vocabulary() {
+            prefixTable.push_back("xml");
+            namespaceNameTable.push_back("http://www.w3.org/XML/1998/namespace");
+        }
+    };
+
+    const Attribute* getAttributeByName(const char* name) const {
+        if (!name) {
+            return 0;
+        }
+        std::string n = name;
+        for (int i=0; i<(int)attributes.size(); ++i) {
+            if (attributes[i].name == n) {
+                return &attributes[i];
+            }
+        }
+        return 0;
+    }
+
+    size_t parseInt2() { // C.25
+        uint8_t b = *dataP++;
+        if (!(b & 0x40)) { // x0...... (C.25.2)
+            return b & 0x3f;
+        }
+        else if ((b & 0x60) == 0x40) { // x10..... ........ (C.25.3)
+            if (dataEnd - dataP > 0) {
+                return (((b & 0x1f) << 8) | *dataP++) + 0x40;
+            }
+        }
+        else if ((b & 0x70) == 0x60) { // x110.... ........ ........ (C.25.4)
+            if (dataEnd - dataP > 1) {
+                size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x2040;
+                dataP += 2;
+                return result;
+            }
+        }
+        throw DeadlyImportError(parseErrorMessage);
+    }
+
+    size_t parseInt3() { // C.27
+        uint8_t b = *dataP++;
+        if (!(b & 0x20)) { // xx0..... (C.27.2)
+            return b & 0x1f;
+        }
+        else if ((b & 0x38) == 0x20) { // xx100... ........ (C.27.3)
+            if (dataEnd - dataP > 0) {
+                return (((b & 0x07) << 8) | *dataP++) + 0x20;
+            }
+        }
+        else if ((b & 0x38) == 0x28) { // xx101... ........ ........ (C.27.4)
+            if (dataEnd - dataP > 1) {
+                size_t result = (((b & 0x07) << 16) | (dataP[0] << 8) | dataP[1]) + 0x820;
+                dataP += 2;
+                return result;
+            }
+        }
+        else if ((b & 0x3f) == 0x30) { // xx110000 0000.... ........ ........ (C.27.5)
+            if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
+                size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x80820;
+                dataP += 3;
+                return result;
+            }
+        }
+        throw DeadlyImportError(parseErrorMessage);
+    }
+
+    size_t parseInt4() { // C.28
+        uint8_t b = *dataP++;
+        if (!(b & 0x10)) { // xxx0.... (C.28.2)
+            return b & 0x0f;
+        }
+        else if ((b & 0x1c) == 0x10) { // xxx100.. ........ (C.28.3)
+            if (dataEnd - dataP > 0) {
+                return (((b & 0x03) << 8) | *dataP++) + 0x10;
+            }
+        }
+        else if ((b & 0x1c) == 0x14) { // xxx101.. ........ ........ (C.28.4)
+            if (dataEnd - dataP > 1) {
+                size_t result = (((b & 0x03) << 16) | (dataP[0] << 8) | dataP[1]) + 0x410;
+                dataP += 2;
+                return result;
+            }
+        }
+        else if ((b & 0x1f) == 0x18) { // xxx11000 0000.... ........ ........ (C.28.5)
+            if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
+                size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x40410;
+                dataP += 3;
+                return result;
+            }
+        }
+        throw DeadlyImportError(parseErrorMessage);
+    }
+
+    size_t parseSequenceLen() { // C.21
+        if (dataEnd - dataP > 0) {
+            uint8_t b = *dataP++;
+            if (b < 0x80) { // 0....... (C.21.2)
+                return b;
+            }
+            else if ((b & 0xf0) == 0x80) { // 1000.... ........ ........ (C.21.3)
+                if (dataEnd - dataP > 1) {
+                    size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x80;
+                    dataP += 2;
+                    return result;
+                }
+            }
+        }
+        throw DeadlyImportError(parseErrorMessage);
+    }
+
+    std::string parseNonEmptyOctetString2() { // C.22
+        // Parse the length of the string
+        uint8_t b = *dataP++ & 0x7f;
+        size_t len;
+        if (!(b & 0x40)) { // x0...... (C.22.3.1)
+            len = b + 1;
+        }
+        else if (b == 0x40) { // x1000000 ........ (C.22.3.2)
+            if (dataEnd - dataP < 1) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            len = *dataP++ + 0x41;
+        }
+        else if (b == 0x60) { // x1100000 ........ ........ ........ ........ (C.22.3.3)
+            if (dataEnd - dataP < 4) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            len = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x141;
+            dataP += 4;
+        }
+        else {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+
+        // Parse the string (C.22.4)
+        if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        std::string s = parseUTF8String(dataP, len);
+        dataP += len;
+
+        return s;
+    }
+
+    size_t parseNonEmptyOctetString5Length() { // C.23
+        // Parse the length of the string
+        size_t b = *dataP++ & 0x0f;
+        if (!(b & 0x08)) { // xxxx0... (C.23.3.1)
+            return b + 1;
+        }
+        else if (b == 0x08) { // xxxx1000 ........ (C.23.3.2)
+            if (dataEnd - dataP > 0) {
+                return *dataP++ + 0x09;
+            }
+        }
+        else if (b == 0x0c) { // xxxx1100 ........ ........ ........ ........ (C.23.3.3)
+            if (dataEnd - dataP > 3) {
+                size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x109;
+                dataP += 4;
+                return result;
+            }
+        }
+        throw DeadlyImportError(parseErrorMessage);
+    }
+
+    size_t parseNonEmptyOctetString7Length() { // C.24
+        // Parse the length of the string
+        size_t b = *dataP++ & 0x03;
+        if (!(b & 0x02)) { // xxxxxx0. (C.24.3.1)
+            return b + 1;
+        }
+        else if (b == 0x02) { // xxxxxx10 ........ (C.24.3.2)
+            if (dataEnd - dataP > 0) {
+                return *dataP++ + 0x3;
+            }
+        }
+        else if (b == 0x03) { // xxxxxx11 ........ ........ ........ ........ (C.24.3.3)
+            if (dataEnd - dataP > 3) {
+                size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x103;
+                dataP += 4;
+                return result;
+            }
+        }
+        throw DeadlyImportError(parseErrorMessage);
+    }
+
+    std::shared_ptr<const FIValue> parseEncodedData(size_t index, size_t len) {
+        if (index < 32) {
+            FIDecoder *decoder = defaultDecoder[index];
+            if (!decoder) {
+                throw DeadlyImportError("Invalid encoding algorithm index " + std::to_string(index));
+            }
+            return decoder->decode(dataP, len);
+        }
+        else {
+            if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) {
+                throw DeadlyImportError("Invalid encoding algorithm index " + std::to_string(index));
+            }
+            std::string uri = vocabulary.encodingAlgorithmTable[index - 32];
+            auto it = decoderMap.find(uri);
+            if (it == decoderMap.end()) {
+                throw DeadlyImportError("Unsupported encoding algorithm " + uri);
+            }
+            else {
+                return it->second->decode(dataP, len);
+            }
+        }
+    }
+
+    std::shared_ptr<const FIValue> parseRestrictedAlphabet(size_t index, size_t len) {
+        std::string alphabet;
+        if (index < 16) {
+            switch (index) {
+            case 0: // numeric
+                alphabet = "0123456789-+.e ";
+                break;
+            case 1: // date and time
+                alphabet = "0123456789-:TZ ";
+                break;
+            default:
+                throw DeadlyImportError("Invalid restricted alphabet index " + std::to_string(index));
+            }
+        }
+        else {
+            if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) {
+                throw DeadlyImportError("Invalid restricted alphabet index " + std::to_string(index));
+            }
+            alphabet = vocabulary.restrictedAlphabetTable[index - 16];
+        }
+        std::vector<uint32_t> alphabetUTF32;
+        utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32));
+        std::string::size_type alphabetLength = alphabetUTF32.size();
+        if (alphabetLength < 2) {
+            throw DeadlyImportError("Invalid restricted alphabet length " + std::to_string(alphabetLength));
+        }
+        std::string::size_type bitsPerCharacter = 1;
+        while ((1ull << bitsPerCharacter) <= alphabetLength) {
+            ++bitsPerCharacter;
+        }
+        size_t bitsAvail = 0;
+        uint8_t mask = (1 << bitsPerCharacter) - 1;
+        uint32_t bits = 0;
+        std::string s;
+        for (size_t i = 0; i < len; ++i) {
+            bits = (bits << 8) | dataP[i];
+            bitsAvail += 8;
+            while (bitsAvail >= bitsPerCharacter) {
+                bitsAvail -= bitsPerCharacter;
+                size_t charIndex = (bits >> bitsAvail) & mask;
+                if (charIndex < alphabetLength) {
+                    s.push_back(alphabetUTF32[charIndex]);
+                }
+                else if (charIndex != mask) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+            }
+        }
+        return FIStringValue::create(std::move(s));
+    }
+
+    std::shared_ptr<const FIValue> parseEncodedCharacterString3() { // C.19
+        std::shared_ptr<const FIValue> result;
+        size_t len;
+        uint8_t b = *dataP;
+        if (b & 0x20) {
+            ++dataP;
+            if (dataEnd - dataP < 1) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            size_t index = ((b & 0x0f) << 4) | ((*dataP & 0xf0) >> 4); // C.29
+            len = parseNonEmptyOctetString5Length();
+            if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            if (b & 0x10) {
+                // encoding algorithm (C.19.3.4)
+                result = parseEncodedData(index, len);
+            }
+            else {
+                // Restricted alphabet (C.19.3.3)
+                result = parseRestrictedAlphabet(index, len);
+            }
+        }
+        else {
+            len = parseNonEmptyOctetString5Length();
+            if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            if (b & 0x10) {
+                // UTF-16 (C.19.3.2)
+                if (len & 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                result = FIStringValue::create(parseUTF16String(dataP, len));
+            }
+            else {
+                // UTF-8 (C.19.3.1)
+                result = FIStringValue::create(parseUTF8String(dataP, len));
+            }
+        }
+        dataP += len;
+        return result;
+    }
+
+    std::shared_ptr<const FIValue> parseEncodedCharacterString5() { // C.20
+        std::shared_ptr<const FIValue> result;
+        size_t len;
+        uint8_t b = *dataP;
+        if (b & 0x08) {
+            ++dataP;
+            if (dataEnd - dataP < 1) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            size_t index = ((b & 0x03) << 6) | ((*dataP & 0xfc) >> 2); /* C.29 */
+            len = parseNonEmptyOctetString7Length();
+            if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            if (b & 0x04) {
+                // encoding algorithm (C.20.3.4)
+                result = parseEncodedData(index, len);
+            }
+            else {
+                // Restricted alphabet (C.20.3.3)
+                result = parseRestrictedAlphabet(index, len);
+            }
+        }
+        else {
+            len = parseNonEmptyOctetString7Length();
+            if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            if (b & 0x04) {
+                // UTF-16 (C.20.3.2)
+                if (len & 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                result = FIStringValue::create(parseUTF16String(dataP, len));
+            }
+            else {
+                // UTF-8 (C.20.3.1)
+                result = FIStringValue::create(parseUTF8String(dataP, len));
+            }
+        }
+        dataP += len;
+        return result;
+    }
+
+    const std::string &parseIdentifyingStringOrIndex(std::vector<std::string> &stringTable) { // C.13
+        if (dataEnd - dataP < 1) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        uint8_t b = *dataP;
+        if (b & 0x80) {
+            // We have an index (C.13.4)
+            size_t index = parseInt2();
+            if (index >= stringTable.size()) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            return stringTable[index];
+        }
+        else {
+            // We have a string (C.13.3)
+            stringTable.push_back(parseNonEmptyOctetString2());
+            return stringTable.back();
+        }
+    }
+
+    QName parseNameSurrogate() { // C.16
+        if (dataEnd - dataP < 1) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        uint8_t b = *dataP++;
+        if (b & 0xfc) { // Padding '000000' C.2.5.5
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        QName result;
+        size_t index;
+        if (b & 0x02) { // prefix (C.16.3)
+            if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            index = parseInt2();
+            if (index >= vocabulary.prefixTable.size()) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            result.prefix = vocabulary.prefixTable[index];
+        }
+        if (b & 0x01) { // namespace-name (C.16.4)
+            if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            index = parseInt2();
+            if (index >= vocabulary.namespaceNameTable.size()) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            result.uri = vocabulary.namespaceNameTable[index];
+        }
+        // local-name
+        if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        index = parseInt2();
+        if (index >= vocabulary.localNameTable.size()) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        result.name = vocabulary.localNameTable[index];
+        return result;
+    }
+
+    const QName &parseQualifiedNameOrIndex2(std::vector<QName> &qNameTable) { // C.17
+        uint8_t b = *dataP;
+        if ((b & 0x7c) == 0x78) { // x11110..
+            // We have a literal (C.17.3)
+            ++dataP;
+            QName result;
+            // prefix (C.17.3.1)
+            result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+            // namespace-name (C.17.3.1)
+            result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+            // local-name
+            result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
+            qNameTable.push_back(result);
+            return qNameTable.back();
+        }
+        else {
+            // We have an index (C.17.4)
+            size_t index = parseInt2();
+            if (index >= qNameTable.size()) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            return qNameTable[index];
+        }
+    }
+
+    const QName &parseQualifiedNameOrIndex3(std::vector<QName> &qNameTable) { // C.18
+        uint8_t b = *dataP;
+        if ((b & 0x3c) == 0x3c) { // xx1111..
+            // We have a literal (C.18.3)
+            ++dataP;
+            QName result;
+            // prefix (C.18.3.1)
+            result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+            // namespace-name (C.18.3.1)
+            result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+            // local-name
+            result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
+            qNameTable.push_back(result);
+            return qNameTable.back();
+        }
+        else {
+            // We have an index (C.18.4)
+            size_t index = parseInt3();
+            if (index >= qNameTable.size()) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            return qNameTable[index];
+        }
+    }
+
+    std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex1(std::vector<std::shared_ptr<const FIValue>> &valueTable) { // C.14
+        uint8_t b = *dataP;
+        if (b == 0xff) { // C.26.2
+            // empty string
+            ++dataP;
+            return EmptyFIString;
+        }
+        else if (b & 0x80) { // C.14.4
+            // We have an index
+            size_t index = parseInt2();
+            if (index >= valueTable.size()) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            return valueTable[index];
+        }
+        else { // C.14.3
+            // We have a literal
+            std::shared_ptr<const FIValue> result = parseEncodedCharacterString3();
+            if (b & 0x40) { // C.14.3.1
+                valueTable.push_back(result);
+            }
+            return result;
+        }
+    }
+
+    std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex3(std::vector<std::shared_ptr<const FIValue>> &valueTable) { // C.15
+        uint8_t b = *dataP;
+        if (b & 0x20) { // C.15.4
+            // We have an index
+            size_t index = parseInt4();
+            if (index >= valueTable.size()) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            return valueTable[index];
+        }
+        else { // C.15.3
+            // We have a literal
+            std::shared_ptr<const FIValue> result = parseEncodedCharacterString5();
+            if (b & 0x10) { // C.15.3.1
+                valueTable.push_back(result);
+            }
+            return result;
+        }
+    }
+
+    void parseElement() {
+        // C.3
+
+        attributes.clear();
+
+        uint8_t b = *dataP;
+        bool hasAttributes = (b & 0x40) != 0; // C.3.3
+        if ((b & 0x3f) == 0x38) { // C.3.4.1
+            // Parse namespaces
+            ++dataP;
+            for (;;) {
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                b = *dataP++;
+                if (b == 0xf0) { // C.3.4.3
+                    break;
+                }
+                if ((b & 0xfc) != 0xcc) { // C.3.4.2
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                // C.12
+                Attribute attr;
+                attr.qname.prefix = "xmlns";
+                attr.qname.name = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+                attr.qname.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+                attr.name = attr.qname.name.empty() ? "xmlns" : "xmlns:" + attr.qname.name;
+                attr.value = FIStringValue::create(std::string(attr.qname.uri));
+                attributes.push_back(attr);
+            }
+            if ((dataEnd - dataP < 1) || (*dataP & 0xc0)) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+        }
+
+        // Parse Element name (C.3.5)
+        const QName &elemName = parseQualifiedNameOrIndex3(vocabulary.elementNameTable);
+        nodeName = elemName.prefix.empty() ? elemName.name : elemName.prefix + ':' + elemName.name;
+
+        if (hasAttributes) {
+            for (;;) {
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                b = *dataP;
+                if (b < 0x80) { // C.3.6.1
+                    // C.4
+                    Attribute attr;
+                    attr.qname = parseQualifiedNameOrIndex2(vocabulary.attributeNameTable);
+                    attr.name = attr.qname.prefix.empty() ? attr.qname.name : attr.qname.prefix + ':' + attr.qname.name;
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    attr.value = parseNonIdentifyingStringOrIndex1(vocabulary.attributeValueTable);
+                    attributes.push_back(attr);
+                }
+                else {
+                    if ((b & 0xf0) != 0xf0) { // C.3.6.2
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    emptyElement = b == 0xff; // C.3.6.2, C.3.8
+                    ++dataP;
+                    break;
+                }
+            }
+        }
+        else {
+            if (dataEnd - dataP < 1) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            b = *dataP;
+            switch (b) {
+            case 0xff:
+                terminatorPending = true;
+                // Intentionally fall through
+            case 0xf0:
+                emptyElement = true;
+                ++dataP;
+                break;
+            default:
+                emptyElement = false;
+            }
+        }
+        if (!emptyElement) {
+            elementStack.push(nodeName);
+        }
+
+        currentNodeType = irr::io::EXN_ELEMENT;
+    }
+
+    void parseHeader() {
+        // Parse header (C.1.3)
+        size_t magicSize = parseMagic(dataP, dataEnd);
+        if (!magicSize) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        dataP += magicSize;
+        // C.2.3
+        if (dataEnd - dataP < 1) {
+            throw DeadlyImportError(parseErrorMessage);
+        }
+        uint8_t b = *dataP++;
+        if (b & 0x40) {
+            // Parse additional data (C.2.4)
+            size_t len = parseSequenceLen();
+            for (size_t i = 0; i < len; ++i) {
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                /*std::string id =*/ parseNonEmptyOctetString2();
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                /*std::string data =*/ parseNonEmptyOctetString2();
+            }
+        }
+        if (b & 0x20) {
+            // Parse initial vocabulary (C.2.5)
+            if (dataEnd - dataP < 2) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            uint16_t b1 = (dataP[0] << 8) | dataP[1];
+            dataP += 2;
+            if (b1 & 0x1000) {
+                // External vocabulary (C.2.5.2)
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                std::string uri = parseNonEmptyOctetString2();
+                auto it = vocabularyMap.find(uri);
+                if (it == vocabularyMap.end()) {
+                    throw DeadlyImportError("Unknown vocabulary " + uri);
+                }
+                const FIVocabulary *externalVocabulary = it->second;
+                if (externalVocabulary->restrictedAlphabetTable) {
+                    std::copy(externalVocabulary->restrictedAlphabetTable, externalVocabulary->restrictedAlphabetTable + externalVocabulary->restrictedAlphabetTableSize, std::back_inserter(vocabulary.restrictedAlphabetTable));
+                }
+                if (externalVocabulary->encodingAlgorithmTable) {
+                    std::copy(externalVocabulary->encodingAlgorithmTable, externalVocabulary->encodingAlgorithmTable + externalVocabulary->encodingAlgorithmTableSize, std::back_inserter(vocabulary.encodingAlgorithmTable));
+                }
+                if (externalVocabulary->prefixTable) {
+                    std::copy(externalVocabulary->prefixTable, externalVocabulary->prefixTable + externalVocabulary->prefixTableSize, std::back_inserter(vocabulary.prefixTable));
+                }
+                if (externalVocabulary->namespaceNameTable) {
+                    std::copy(externalVocabulary->namespaceNameTable, externalVocabulary->namespaceNameTable + externalVocabulary->namespaceNameTableSize, std::back_inserter(vocabulary.namespaceNameTable));
+                }
+                if (externalVocabulary->localNameTable) {
+                    std::copy(externalVocabulary->localNameTable, externalVocabulary->localNameTable + externalVocabulary->localNameTableSize, std::back_inserter(vocabulary.localNameTable));
+                }
+                if (externalVocabulary->otherNCNameTable) {
+                    std::copy(externalVocabulary->otherNCNameTable, externalVocabulary->otherNCNameTable + externalVocabulary->otherNCNameTableSize, std::back_inserter(vocabulary.otherNCNameTable));
+                }
+                if (externalVocabulary->otherURITable) {
+                    std::copy(externalVocabulary->otherURITable, externalVocabulary->otherURITable + externalVocabulary->otherURITableSize, std::back_inserter(vocabulary.otherURITable));
+                }
+                if (externalVocabulary->attributeValueTable) {
+                    std::copy(externalVocabulary->attributeValueTable, externalVocabulary->attributeValueTable + externalVocabulary->attributeValueTableSize, std::back_inserter(vocabulary.attributeValueTable));
+                }
+                if (externalVocabulary->charactersTable) {
+                    std::copy(externalVocabulary->charactersTable, externalVocabulary->charactersTable + externalVocabulary->charactersTableSize, std::back_inserter(vocabulary.charactersTable));
+                }
+                if (externalVocabulary->otherStringTable) {
+                    std::copy(externalVocabulary->otherStringTable, externalVocabulary->otherStringTable + externalVocabulary->otherStringTableSize, std::back_inserter(vocabulary.otherStringTable));
+                }
+                if (externalVocabulary->elementNameTable) {
+                    std::copy(externalVocabulary->elementNameTable, externalVocabulary->elementNameTable + externalVocabulary->elementNameTableSize, std::back_inserter(vocabulary.elementNameTable));
+                }
+                if (externalVocabulary->attributeNameTable) {
+                    std::copy(externalVocabulary->attributeNameTable, externalVocabulary->attributeNameTable + externalVocabulary->attributeNameTableSize, std::back_inserter(vocabulary.attributeNameTable));
+                }
+            }
+            if (b1 & 0x0800) {
+                // Parse restricted alphabets (C.2.5.3)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.restrictedAlphabetTable.push_back(parseNonEmptyOctetString2());
+                }
+            }
+            if (b1 & 0x0400) {
+                // Parse encoding algorithms (C.2.5.3)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.encodingAlgorithmTable.push_back(parseNonEmptyOctetString2());
+                }
+            }
+            if (b1 & 0x0200) {
+                // Parse prefixes (C.2.5.3)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.prefixTable.push_back(parseNonEmptyOctetString2());
+                }
+            }
+            if (b1 & 0x0100) {
+                // Parse namespace names (C.2.5.3)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.namespaceNameTable.push_back(parseNonEmptyOctetString2());
+                }
+            }
+            if (b1 & 0x0080) {
+                // Parse local names (C.2.5.3)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.localNameTable.push_back(parseNonEmptyOctetString2());
+                }
+            }
+            if (b1 & 0x0040) {
+                // Parse other ncnames (C.2.5.3)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.otherNCNameTable.push_back(parseNonEmptyOctetString2());
+                }
+            }
+            if (b1 & 0x0020) {
+                // Parse other uris (C.2.5.3)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.otherURITable.push_back(parseNonEmptyOctetString2());
+                }
+            }
+            if (b1 & 0x0010) {
+                // Parse attribute values (C.2.5.4)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.attributeValueTable.push_back(parseEncodedCharacterString3());
+                }
+            }
+            if (b1 & 0x0008) {
+                // Parse content character chunks (C.2.5.4)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.charactersTable.push_back(parseEncodedCharacterString3());
+                }
+            }
+            if (b1 & 0x0004) {
+                // Parse other strings (C.2.5.4)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    if (dataEnd - dataP < 1) {
+                        throw DeadlyImportError(parseErrorMessage);
+                    }
+                    vocabulary.otherStringTable.push_back(parseEncodedCharacterString3());
+                }
+            }
+            if (b1 & 0x0002) {
+                // Parse element name surrogates (C.2.5.5)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    vocabulary.elementNameTable.push_back(parseNameSurrogate());
+                }
+            }
+            if (b1 & 0x0001) {
+                // Parse attribute name surrogates (C.2.5.5)
+                for (size_t len = parseSequenceLen(); len > 0; --len) {
+                    vocabulary.attributeNameTable.push_back(parseNameSurrogate());
+                }
+            }
+        }
+        if (b & 0x10) {
+            // Parse notations (C.2.6)
+            for (;;) {
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                uint8_t b1 = *dataP++;
+                if (b1 == 0xf0) {
+                    break;
+                }
+                if ((b1 & 0xfc) != 0xc0) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                /* C.11 */
+                /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+                if (b1 & 0x02) {
+                    /*const std::string &systemId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+                }
+                if (b1 & 0x01) {
+                    /*const std::string &publicId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+                }
+            }
+        }
+        if (b & 0x08) {
+            // Parse unparsed entities (C.2.7)
+            for (;;) {
+                if (dataEnd - dataP < 1) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                uint8_t b1 = *dataP++;
+                if (b1 == 0xf0) {
+                    break;
+                }
+                if ((b1 & 0xfe) != 0xd0) {
+                    throw DeadlyImportError(parseErrorMessage);
+                }
+                /* C.10 */
+                /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+                /*const std::string &systemId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+                if (b1 & 0x01) {
+                    /*const std::string &publicId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+                }
+                /*const std::string &notationName =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+            }
+        }
+        if (b & 0x04) {
+            // Parse character encoding scheme (C.2.8)
+            if (dataEnd - dataP < 1) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            /*std::string characterEncodingScheme =*/ parseNonEmptyOctetString2();
+        }
+        if (b & 0x02) {
+            // Parse standalone flag (C.2.9)
+            if (dataEnd - dataP < 1) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            uint8_t b1 = *dataP++;
+            if (b1 & 0xfe) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            //bool standalone = b1 & 0x01;
+        }
+        if (b & 0x01) {
+            // Parse version (C.2.10)
+            if (dataEnd - dataP < 1) {
+                throw DeadlyImportError(parseErrorMessage);
+            }
+            /*std::shared_ptr<const FIValue> version =*/ parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+        }
+    }
+
+    std::unique_ptr<uint8_t[]> data;
+    uint8_t *dataP, *dataEnd;
+    irr::io::EXML_NODE currentNodeType;
+    bool emptyElement;
+    bool headerPending;
+    bool terminatorPending;
+    Vocabulary vocabulary;
+    std::vector<Attribute> attributes;
+    std::stack<std::string> elementStack;
+    std::string nodeName;
+    std::map<std::string, std::unique_ptr<FIDecoder>> decoderMap;
+    std::map<std::string, const FIVocabulary*> vocabularyMap;
+
+    static const std::string EmptyString;
+    static std::shared_ptr<const FIValue> EmptyFIString;
+
+    static FIHexDecoder hexDecoder;
+    static FIBase64Decoder base64Decoder;
+    static FIShortDecoder shortDecoder;
+    static FIIntDecoder intDecoder;
+    static FILongDecoder longDecoder;
+    static FIBoolDecoder boolDecoder;
+    static FIFloatDecoder floatDecoder;
+    static FIDoubleDecoder doubleDecoder;
+    static FIUUIDDecoder uuidDecoder;
+    static FICDATADecoder cdataDecoder;
+    static FIDecoder *defaultDecoder[32];
+};
+
+const std::string CFIReaderImpl::EmptyString;
+std::shared_ptr<const FIValue> CFIReaderImpl::EmptyFIString = FIStringValue::create(std::string());
+
+FIHexDecoder CFIReaderImpl::hexDecoder;
+FIBase64Decoder CFIReaderImpl::base64Decoder;
+FIShortDecoder CFIReaderImpl::shortDecoder;
+FIIntDecoder CFIReaderImpl::intDecoder;
+FILongDecoder CFIReaderImpl::longDecoder;
+FIBoolDecoder CFIReaderImpl::boolDecoder;
+FIFloatDecoder CFIReaderImpl::floatDecoder;
+FIDoubleDecoder CFIReaderImpl::doubleDecoder;
+FIUUIDDecoder CFIReaderImpl::uuidDecoder;
+FICDATADecoder CFIReaderImpl::cdataDecoder;
+
+FIDecoder *CFIReaderImpl::defaultDecoder[32] = {
+    &hexDecoder,
+    &base64Decoder,
+    &shortDecoder,
+    &intDecoder,
+    &longDecoder,
+    &boolDecoder,
+    &floatDecoder,
+    &doubleDecoder,
+    &uuidDecoder,
+    &cdataDecoder
+};
+
+class CXMLReaderImpl : public FIReader
+{
+public:
+
+    //! Constructor
+    CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader_)
+    : reader(std::move(reader_))
+    {}
+
+    virtual ~CXMLReaderImpl() {}
+
+    virtual bool read() /*override*/ {
+        return reader->read();
+    }
+
+    virtual irr::io::EXML_NODE getNodeType() const /*override*/ {
+        return reader->getNodeType();
+    }
+
+    virtual int getAttributeCount() const /*override*/ {
+        return reader->getAttributeCount();
+    }
+
+    virtual const char* getAttributeName(int idx) const /*override*/ {
+        return reader->getAttributeName(idx);
+    }
+
+    virtual const char* getAttributeValue(int idx) const /*override*/ {
+        return reader->getAttributeValue(idx);
+    }
+
+    virtual const char* getAttributeValue(const char* name) const /*override*/ {
+        return reader->getAttributeValue(name);
+    }
+
+    virtual const char* getAttributeValueSafe(const char* name) const /*override*/ {
+        return reader->getAttributeValueSafe(name);
+    }
+
+    virtual int getAttributeValueAsInt(const char* name) const /*override*/ {
+        return reader->getAttributeValueAsInt(name);
+    }
+
+    virtual int getAttributeValueAsInt(int idx) const /*override*/ {
+        return reader->getAttributeValueAsInt(idx);
+    }
+
+    virtual float getAttributeValueAsFloat(const char* name) const /*override*/ {
+        return reader->getAttributeValueAsFloat(name);
+    }
+
+    virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
+        return reader->getAttributeValueAsFloat(idx);
+    }
+
+    virtual const char* getNodeName() const /*override*/ {
+        return reader->getNodeName();
+    }
+
+    virtual const char* getNodeData() const /*override*/ {
+        return reader->getNodeData();
+    }
+
+    virtual bool isEmptyElement() const /*override*/ {
+        return reader->isEmptyElement();
+    }
+
+    virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ {
+        return reader->getSourceFormat();
+    }
+
+    virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ {
+        return reader->getParserFormat();
+    }
+
+    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const /*override*/ {
+        return nullptr;
+    }
+
+    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char* name) const /*override*/ {
+        return nullptr;
+    }
+
+    virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) /*override*/ {}
+
+    virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) /*override*/ {}
+
+private:
+
+    std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader;
+};
+
+static std::unique_ptr<uint8_t[]> readFile(IOStream *stream, size_t &size, bool &isFI) {
+    size = stream->FileSize();
+    std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
+    if (stream->Read(data.get(), size, 1) != 1) {
+        size = 0;
+        data.reset();
+    }
+    isFI = parseMagic(data.get(), data.get() + size) > 0;
+    return data;
+}
+
+std::unique_ptr<FIReader> FIReader::create(IOStream *stream)
+{
+    size_t size;
+    bool isFI;
+    auto data = readFile(stream, size, isFI);
+    if (isFI) {
+        return std::unique_ptr<FIReader>(new CFIReaderImpl(std::move(data), size));
+    }
+    else {
+        auto memios = std::unique_ptr<MemoryIOStream>(new MemoryIOStream(data.release(), size, true));
+        auto callback = std::unique_ptr<CIrrXML_IOStreamReader>(new CIrrXML_IOStreamReader(memios.get()));
+        return std::unique_ptr<FIReader>(new CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>>(createIrrXMLReader(callback.get()))));
+    }
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 172 - 0
code/FIReader.hpp

@@ -0,0 +1,172 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/// \file   FIReader.hpp
+/// \brief  Reader for Fast Infoset encoded binary XML files.
+/// \date   2017
+/// \author Patrick Daehne
+
+#ifndef INCLUDED_AI_FI_READER_H
+#define INCLUDED_AI_FI_READER_H
+
+#include <irrXML.h>
+#include <memory>
+#include <string>
+#include <vector>
+#include <cstdint>
+
+namespace Assimp {
+
+struct FIValue {
+    virtual const std::string &toString() const = 0;
+};
+
+struct FIStringValue: public FIValue {
+    std::string value;
+    static std::shared_ptr<FIStringValue> create(std::string &&value);
+};
+
+struct FIByteValue: public FIValue {
+    std::vector<uint8_t> value;
+};
+
+struct FIHexValue: public FIByteValue {
+    static std::shared_ptr<FIHexValue> create(std::vector<uint8_t> &&value);
+};
+
+struct FIBase64Value: public FIByteValue {
+    static std::shared_ptr<FIBase64Value> create(std::vector<uint8_t> &&value);
+};
+
+struct FIShortValue: public FIValue {
+    std::vector<int16_t> value;
+    static std::shared_ptr<FIShortValue> create(std::vector<int16_t> &&value);
+};
+
+struct FIIntValue: public FIValue {
+    std::vector<int32_t> value;
+    static std::shared_ptr<FIIntValue> create(std::vector<int32_t> &&value);
+};
+
+struct FILongValue: public FIValue {
+    std::vector<int64_t> value;
+    static std::shared_ptr<FILongValue> create(std::vector<int64_t> &&value);
+};
+
+struct FIBoolValue: public FIValue {
+    std::vector<bool> value;
+    static std::shared_ptr<FIBoolValue> create(std::vector<bool> &&value);
+};
+
+struct FIFloatValue: public FIValue {
+    std::vector<float> value;
+    static std::shared_ptr<FIFloatValue> create(std::vector<float> &&value);
+};
+
+struct FIDoubleValue: public FIValue {
+    std::vector<double> value;
+    static std::shared_ptr<FIDoubleValue> create(std::vector<double> &&value);
+};
+
+struct FIUUIDValue: public FIByteValue {
+    static std::shared_ptr<FIUUIDValue> create(std::vector<uint8_t> &&value);
+};
+
+struct FICDATAValue: public FIStringValue {
+    static std::shared_ptr<FICDATAValue> create(std::string &&value);
+};
+
+struct FIDecoder {
+    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) = 0;
+};
+
+struct FIQName {
+    const char *name;
+    const char *prefix;
+    const char *uri;
+};
+
+struct FIVocabulary {
+    const char **restrictedAlphabetTable;
+    size_t restrictedAlphabetTableSize;
+    const char **encodingAlgorithmTable;
+    size_t encodingAlgorithmTableSize;
+    const char **prefixTable;
+    size_t prefixTableSize;
+    const char **namespaceNameTable;
+    size_t namespaceNameTableSize;
+    const char **localNameTable;
+    size_t localNameTableSize;
+    const char **otherNCNameTable;
+    size_t otherNCNameTableSize;
+    const char **otherURITable;
+    size_t otherURITableSize;
+    const std::shared_ptr<const FIValue> *attributeValueTable;
+    size_t attributeValueTableSize;
+    const std::shared_ptr<const FIValue> *charactersTable;
+    size_t charactersTableSize;
+    const std::shared_ptr<const FIValue> *otherStringTable;
+    size_t otherStringTableSize;
+    const FIQName *elementNameTable;
+    size_t elementNameTableSize;
+    const FIQName *attributeNameTable;
+    size_t attributeNameTableSize;
+};
+
+class IOStream;
+
+class FIReader: public irr::io::IIrrXMLReader<char, irr::io::IXMLBase> {
+public:
+
+    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const = 0;
+
+    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char *name) const = 0;
+
+    virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) = 0;
+
+    virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) = 0;
+
+    static std::unique_ptr<FIReader> create(IOStream *stream);
+
+};// class IFIReader
+
+}// namespace Assimp
+
+#endif // INCLUDED_AI_FI_READER_H

+ 2 - 3
code/HalfLifeFileData.h

@@ -66,8 +66,7 @@ namespace MDL   {
  *  \brief Data structure for the HL2 main header
  *  \brief Data structure for the HL2 main header
  */
  */
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
-struct Header_HL2
-{
+struct Header_HL2 {
     //! magic number: "IDST"/"IDSQ"
     //! magic number: "IDST"/"IDSQ"
     char    ident[4];
     char    ident[4];
 
 
@@ -139,7 +138,7 @@ struct Header_HL2
     //! Number of animation transitions
     //! Number of animation transitions
     int32_t         numtransitions;
     int32_t         numtransitions;
     int32_t         transitionindex;
     int32_t         transitionindex;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #include "./../include/assimp/Compiler/poppack1.h"
 #include "./../include/assimp/Compiler/poppack1.h"
 
 

+ 1 - 1
code/IRRLoader.cpp

@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "fast_atof.h"
 #include "fast_atof.h"
 #include "GenericProperty.h"
 #include "GenericProperty.h"
 
 
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StandardShapes.h"
 #include "StandardShapes.h"
 #include "Importer.h"
 #include "Importer.h"
 
 

+ 1 - 1
code/IRRLoader.h

@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_IRRLOADER_H_INCLUDED
 #define AI_IRRLOADER_H_INCLUDED
 
 
 #include "IRRShared.h"
 #include "IRRShared.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Importer.h"
 #include "Importer.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
 #include <assimp/anim.h>
 #include <assimp/anim.h>

+ 2 - 0
code/ImporterRegistry.cpp

@@ -231,7 +231,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
     out.push_back( new MDLImporter());
     out.push_back( new MDLImporter());
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
+  #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
     out.push_back( new ASEImporter());
     out.push_back( new ASEImporter());
+#  endif
 #endif
 #endif
 #if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
 #if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
     out.push_back( new HMPImporter());
     out.push_back( new HMPImporter());

+ 2 - 1
code/LWOAnimation.cpp

@@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 // internal headers
 // internal headers
 #include "LWOFileData.h"
 #include "LWOFileData.h"
+#include <assimp/anim.h>
 
 
 using namespace Assimp;
 using namespace Assimp;
 using namespace Assimp::LWO;
 using namespace Assimp::LWO;
@@ -163,7 +164,7 @@ void AnimResolver::UpdateAnimRangeSetup()
                 {
                 {
                 const double start_time = delta - std::fmod(my_first-first,delta);
                 const double start_time = delta - std::fmod(my_first-first,delta);
                 std::vector<LWO::Key>::iterator n = std::find_if((*it).keys.begin(),(*it).keys.end(),
                 std::vector<LWO::Key>::iterator n = std::find_if((*it).keys.begin(),(*it).keys.end(),
-                    std::bind1st(std::greater<double>(),start_time)),m;
+                    [start_time](double t) { return start_time > t; }),m;
 
 
                 size_t ofs = 0;
                 size_t ofs = 0;
                 if (n != (*it).keys.end()) {
                 if (n != (*it).keys.end()) {

+ 3 - 4
code/LWOAnimation.h

@@ -48,11 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_LWO_ANIMATION_INCLUDED
 #ifndef AI_LWO_ANIMATION_INCLUDED
 #define AI_LWO_ANIMATION_INCLUDED
 #define AI_LWO_ANIMATION_INCLUDED
 
 
-#include <assimp/anim.h>
+//
 #include <vector>
 #include <vector>
 #include <list>
 #include <list>
 
 
 struct aiNodeAnim;
 struct aiNodeAnim;
+struct aiVectorKey;
 
 
 namespace Assimp {
 namespace Assimp {
 namespace LWO {
 namespace LWO {
@@ -166,7 +167,6 @@ struct Envelope
     //! Keyframes for this envelope
     //! Keyframes for this envelope
     std::vector<Key> keys;
     std::vector<Key> keys;
 
 
-
     // temporary data for AnimResolver
     // temporary data for AnimResolver
     size_t old_first,old_last;
     size_t old_first,old_last;
 };
 };
@@ -198,8 +198,7 @@ public:
      *  @param Output tick rate, per second
      *  @param Output tick rate, per second
      *  @note The input envelopes are possibly modified.
      *  @note The input envelopes are possibly modified.
      */
      */
-    AnimResolver(std::list<Envelope>& envelopes,
-        double tick);
+    AnimResolver(std::list<Envelope>& envelopes, double tick);
 
 
 public:
 public:
 
 

+ 1 - 1
code/LWSLoader.cpp

@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
 
 
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "GenericProperty.h"
 #include "GenericProperty.h"
 #include "SkeletonMeshBuilder.h"
 #include "SkeletonMeshBuilder.h"
 #include "ConvertToLHProcess.h"
 #include "ConvertToLHProcess.h"

+ 1 - 1
code/LWSLoader.h

@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_LWSLOADER_H_INCLUDED
 #define AI_LWSLOADER_H_INCLUDED
 
 
 #include "LWOFileData.h"
 #include "LWOFileData.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 
 
 struct aiImporterDesc;
 struct aiImporterDesc;

+ 12 - 15
code/MD3FileData.h

@@ -142,14 +142,14 @@ struct Frame
     //! name of frame
     //! name of frame
     char name[ AI_MD3_MAXFRAME ];
     char name[ AI_MD3_MAXFRAME ];
 
 
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
-/** @brief Data structure for the tag header
+/**
+ * @brief Data structure for the tag header
  */
  */
-struct Tag
-{
+struct Tag {
     //! name of the tag
     //! name of the tag
     char NAME[ AI_MD3_MAXQPATH ];
     char NAME[ AI_MD3_MAXQPATH ];
 
 
@@ -157,14 +157,13 @@ struct Tag
     aiVector3D  origin;
     aiVector3D  origin;
     ai_real  orientation[3][3];
     ai_real  orientation[3][3];
 
 
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /** @brief Data structure for the surface header
 /** @brief Data structure for the surface header
  */
  */
-struct Surface
-{
+struct Surface {
     //! magic number
     //! magic number
     int32_t IDENT;
     int32_t IDENT;
 
 
@@ -186,7 +185,6 @@ struct Surface
     //! number of triangles in the surface
     //! number of triangles in the surface
     uint32_t NUM_TRIANGLES;
     uint32_t NUM_TRIANGLES;
 
 
-
     //! offset to the triangle data
     //! offset to the triangle data
     uint32_t OFS_TRIANGLES;
     uint32_t OFS_TRIANGLES;
 
 
@@ -201,19 +199,18 @@ struct Surface
 
 
     //! offset to the end of the Surface object
     //! offset to the end of the Surface object
     int32_t OFS_END;
     int32_t OFS_END;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /** @brief Data structure for a shader defined in there
 /** @brief Data structure for a shader defined in there
  */
  */
-struct Shader
-{
+struct Shader {
     //! filename of the shader
     //! filename of the shader
     char NAME[ AI_MD3_MAXQPATH ];
     char NAME[ AI_MD3_MAXQPATH ];
 
 
     //! index of the shader
     //! index of the shader
     uint32_t SHADER_INDEX;
     uint32_t SHADER_INDEX;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -223,7 +220,7 @@ struct Triangle
 {
 {
     //! triangle indices
     //! triangle indices
     uint32_t INDEXES[3];
     uint32_t INDEXES[3];
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -233,7 +230,7 @@ struct TexCoord
 {
 {
     //! UV coordinates
     //! UV coordinates
     ai_real U,V;
     ai_real U,V;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -246,7 +243,7 @@ struct Vertex
 
 
     //! encoded normal vector
     //! encoded normal vector
     uint16_t  NORMAL;
     uint16_t  NORMAL;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 #include "./../include/assimp/Compiler/poppack1.h"
 #include "./../include/assimp/Compiler/poppack1.h"
 
 

+ 1 - 1
code/MD3Loader.cpp

@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
 #ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
 
 
 #include "MD3Loader.h"
 #include "MD3Loader.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "GenericProperty.h"
 #include "GenericProperty.h"
 #include "RemoveComments.h"
 #include "RemoveComments.h"
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"

+ 1 - 1
code/MDCFileData.h

@@ -157,7 +157,7 @@ struct Frame
 
 
     //! Name of the frame
     //! Name of the frame
     char name [ 16 ] ;
     char name [ 16 ] ;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** \brief Data structure for a MDC triangle
 /** \brief Data structure for a MDC triangle

+ 51 - 76
code/MDLFileData.h

@@ -53,10 +53,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_MDLFILEHELPER_H_INC
 #ifndef AI_MDLFILEHELPER_H_INC
 #define AI_MDLFILEHELPER_H_INC
 #define AI_MDLFILEHELPER_H_INC
 
 
+#include <assimp/anim.h>
+#include <assimp/mesh.h>
+#include <assimp/Compiler/pushpack1.h>
 #include "ByteSwapper.h"
 #include "ByteSwapper.h"
-#include "./../include/assimp/anim.h"
-#include "./../include/assimp/mesh.h"
-#include "./../include/assimp/Compiler/pushpack1.h"
 #include <stdint.h>
 #include <stdint.h>
 #include <vector>
 #include <vector>
 
 
@@ -90,7 +90,6 @@ namespace MDL   {
 #define AI_MDL_MAGIC_NUMBER_BE_GS7  AI_MAKE_MAGIC("MDL7")
 #define AI_MDL_MAGIC_NUMBER_BE_GS7  AI_MAKE_MAGIC("MDL7")
 #define AI_MDL_MAGIC_NUMBER_LE_GS7  AI_MAKE_MAGIC("7LDM")
 #define AI_MDL_MAGIC_NUMBER_LE_GS7  AI_MAKE_MAGIC("7LDM")
 
 
-
 // common limitations for Quake1 meshes. The loader does not check them,
 // common limitations for Quake1 meshes. The loader does not check them,
 // (however it warns) but models should not exceed these limits.
 // (however it warns) but models should not exceed these limits.
 #if (!defined AI_MDL_VERSION)
 #if (!defined AI_MDL_VERSION)
@@ -119,8 +118,7 @@ namespace MDL   {
 /** \struct Header
 /** \struct Header
  *  \brief Data structure for the MDL main header
  *  \brief Data structure for the MDL main header
  */
  */
-struct Header
-{
+struct Header {
     //! magic number: "IDPO"
     //! magic number: "IDPO"
     uint32_t ident;
     uint32_t ident;
 
 
@@ -166,15 +164,14 @@ struct Header
 
 
     //! Could be the total size of the file (and not a float)
     //! Could be the total size of the file (and not a float)
     float size;
     float size;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Header_MDL7
 /** \struct Header_MDL7
  *  \brief Data structure for the MDL 7 main header
  *  \brief Data structure for the MDL 7 main header
  */
  */
-struct Header_MDL7
-{
+struct Header_MDL7 {
     //! magic number: "MDL7"
     //! magic number: "MDL7"
     char    ident[4];
     char    ident[4];
 
 
@@ -226,15 +223,14 @@ struct Header_MDL7
 
 
     //! Size of the Frame_MDL7 data structure used in the file
     //! Size of the Frame_MDL7 data structure used in the file
     uint16_t frame_stc_size;
     uint16_t frame_stc_size;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Bone_MDL7
 /** \struct Bone_MDL7
  *  \brief Data structure for a bone in a MDL7 file
  *  \brief Data structure for a bone in a MDL7 file
  */
  */
-struct Bone_MDL7
-{
+struct Bone_MDL7 {
     //! Index of the parent bone of *this* bone. 0xffff means:
     //! Index of the parent bone of *this* bone. 0xffff means:
     //! "hey, I have no parent, I'm an orphan"
     //! "hey, I have no parent, I'm an orphan"
     uint16_t parent_index;
     uint16_t parent_index;
@@ -246,7 +242,7 @@ struct Bone_MDL7
 
 
     //! Optional name of the bone
     //! Optional name of the bone
     char name[1 /* DUMMY SIZE */];
     char name[1 /* DUMMY SIZE */];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS)
 #if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS)
 #   define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
 #   define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
@@ -268,8 +264,7 @@ struct Bone_MDL7
 /** \struct Group_MDL7
 /** \struct Group_MDL7
  *  \brief Group in a MDL7 file
  *  \brief Group in a MDL7 file
  */
  */
-struct Group_MDL7
-{
+struct Group_MDL7 {
     //! = '1' -> triangle based Mesh
     //! = '1' -> triangle based Mesh
     unsigned char   typ;
     unsigned char   typ;
 
 
@@ -295,7 +290,7 @@ struct Group_MDL7
 
 
     //! Number of frames
     //! Number of frames
     int32_t numframes;
     int32_t numframes;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #define AI_MDL7_SKINTYPE_MIPFLAG                0x08
 #define AI_MDL7_SKINTYPE_MIPFLAG                0x08
 #define AI_MDL7_SKINTYPE_MATERIAL               0x10
 #define AI_MDL7_SKINTYPE_MATERIAL               0x10
@@ -310,41 +305,36 @@ struct Group_MDL7
 /** \struct Deformer_MDL7
 /** \struct Deformer_MDL7
  *  \brief Deformer in a MDL7 file
  *  \brief Deformer in a MDL7 file
  */
  */
-struct Deformer_MDL7
-{
+struct Deformer_MDL7 {
     int8_t  deformer_version;       // 0
     int8_t  deformer_version;       // 0
     int8_t  deformer_typ;           // 0 - bones
     int8_t  deformer_typ;           // 0 - bones
     int8_t  _unused_[2];
     int8_t  _unused_[2];
     int32_t group_index;
     int32_t group_index;
     int32_t elements;
     int32_t elements;
     int32_t deformerdata_size;
     int32_t deformerdata_size;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct DeformerElement_MDL7
 /** \struct DeformerElement_MDL7
  *  \brief Deformer element in a MDL7 file
  *  \brief Deformer element in a MDL7 file
  */
  */
-struct DeformerElement_MDL7
-{
+struct DeformerElement_MDL7 {
     //! bei deformer_typ==0 (==bones) element_index == bone index
     //! bei deformer_typ==0 (==bones) element_index == bone index
     int32_t element_index;
     int32_t element_index;
     char    element_name[AI_MDL7_MAX_BONENAMESIZE];
     char    element_name[AI_MDL7_MAX_BONENAMESIZE];
     int32_t weights;
     int32_t weights;
-} PACK_STRUCT;
-
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct DeformerWeight_MDL7
 /** \struct DeformerWeight_MDL7
  *  \brief Deformer weight in a MDL7 file
  *  \brief Deformer weight in a MDL7 file
  */
  */
-struct DeformerWeight_MDL7
-{
+struct DeformerWeight_MDL7 {
     //! for deformer_typ==0 (==bones) index == vertex index
     //! for deformer_typ==0 (==bones) index == vertex index
     int32_t index;
     int32_t index;
     float   weight;
     float   weight;
-} PACK_STRUCT;
-
+} /* PACK_STRUCT */;
 
 
 // don't know why this was in the original headers ...
 // don't know why this was in the original headers ...
 typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
 typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
@@ -353,17 +343,15 @@ typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
 /** \struct ColorValue_MDL7
 /** \struct ColorValue_MDL7
  *  \brief Data structure for a color value in a MDL7 file
  *  \brief Data structure for a color value in a MDL7 file
  */
  */
-struct ColorValue_MDL7
-{
+struct ColorValue_MDL7 {
     float r,g,b,a;
     float r,g,b,a;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Material_MDL7
 /** \struct Material_MDL7
  *  \brief Data structure for a Material in a MDL7 file
  *  \brief Data structure for a Material in a MDL7 file
  */
  */
-struct Material_MDL7
-{
+struct Material_MDL7 {
     //! Diffuse base color of the material
     //! Diffuse base color of the material
     ColorValue_MDL7 Diffuse;
     ColorValue_MDL7 Diffuse;
 
 
@@ -378,15 +366,13 @@ struct Material_MDL7
 
 
     //! Phong power
     //! Phong power
     float           Power;
     float           Power;
-} PACK_STRUCT;
-
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Skin
 /** \struct Skin
  *  \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4
  *  \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4
  */
  */
-struct Skin
-{
+struct Skin {
     //! 0 = single (Skin), 1 = group (GroupSkin)
     //! 0 = single (Skin), 1 = group (GroupSkin)
     //! For MDL3-5: Defines the type of the skin and there
     //! For MDL3-5: Defines the type of the skin and there
     //! fore the size of the data to skip:
     //! fore the size of the data to skip:
@@ -402,7 +388,7 @@ struct Skin
 
 
     //! Texture data
     //! Texture data
     uint8_t *data;
     uint8_t *data;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
@@ -410,11 +396,10 @@ struct Skin
  *  \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7
  *  \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7
  *  \see Skin
  *  \see Skin
  */
  */
-struct Skin_MDL5
-{
+struct Skin_MDL5 {
     int32_t size, width, height;
     int32_t size, width, height;
     uint8_t *data;
     uint8_t *data;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // maximum length of texture file name
 // maximum length of texture file name
 #if (!defined AI_MDL7_MAX_TEXNAMESIZE)
 #if (!defined AI_MDL7_MAX_TEXNAMESIZE)
@@ -425,44 +410,40 @@ struct Skin_MDL5
 /** \struct Skin_MDL7
 /** \struct Skin_MDL7
  *  \brief Skin data structure #3 - used by MDL7 and HMP7
  *  \brief Skin data structure #3 - used by MDL7 and HMP7
  */
  */
-struct Skin_MDL7
-{
+struct Skin_MDL7 {
     uint8_t         typ;
     uint8_t         typ;
     int8_t          _unused_[3];
     int8_t          _unused_[3];
     int32_t         width;
     int32_t         width;
     int32_t         height;
     int32_t         height;
     char            texture_name[AI_MDL7_MAX_TEXNAMESIZE];
     char            texture_name[AI_MDL7_MAX_TEXNAMESIZE];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct RGB565
 /** \struct RGB565
  *  \brief Data structure for a RGB565 pixel in a texture
  *  \brief Data structure for a RGB565 pixel in a texture
  */
  */
-struct RGB565
-{
+struct RGB565 {
     uint16_t r : 5;
     uint16_t r : 5;
     uint16_t g : 6;
     uint16_t g : 6;
     uint16_t b : 5;
     uint16_t b : 5;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct ARGB4
 /** \struct ARGB4
  *  \brief Data structure for a ARGB4444 pixel in a texture
  *  \brief Data structure for a ARGB4444 pixel in a texture
  */
  */
-struct ARGB4
-{
+struct ARGB4 {
     uint16_t a : 4;
     uint16_t a : 4;
     uint16_t r : 4;
     uint16_t r : 4;
     uint16_t g : 4;
     uint16_t g : 4;
     uint16_t b : 4;
     uint16_t b : 4;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct GroupSkin
 /** \struct GroupSkin
  *  \brief Skin data structure #2 (group of pictures)
  *  \brief Skin data structure #2 (group of pictures)
  */
  */
-struct GroupSkin
-{
+struct GroupSkin {
     //! 0 = single (Skin), 1 = group (GroupSkin)
     //! 0 = single (Skin), 1 = group (GroupSkin)
     int32_t group;
     int32_t group;
 
 
@@ -474,14 +455,13 @@ struct GroupSkin
 
 
     //! Data of each image
     //! Data of each image
     uint8_t **data;
     uint8_t **data;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct TexCoord
 /** \struct TexCoord
  *  \brief Texture coordinate data structure used by the Quake1 MDL format
  *  \brief Texture coordinate data structure used by the Quake1 MDL format
  */
  */
-struct TexCoord
-{
+struct TexCoord {
     //! Is the vertex on the noundary between front and back piece?
     //! Is the vertex on the noundary between front and back piece?
     int32_t onseam;
     int32_t onseam;
 
 
@@ -490,33 +470,31 @@ struct TexCoord
 
 
     //! Texture coordinate in the ty direction
     //! Texture coordinate in the ty direction
     int32_t t;
     int32_t t;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct TexCoord_MDL3
 /** \struct TexCoord_MDL3
  *  \brief Data structure for an UV coordinate in the 3DGS MDL3 format
  *  \brief Data structure for an UV coordinate in the 3DGS MDL3 format
  */
  */
-struct TexCoord_MDL3
-{
+struct TexCoord_MDL3 {
     //! position, horizontally in range 0..skinwidth-1
     //! position, horizontally in range 0..skinwidth-1
     int16_t u;
     int16_t u;
 
 
     //! position, vertically in range 0..skinheight-1
     //! position, vertically in range 0..skinheight-1
     int16_t v;
     int16_t v;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct TexCoord_MDL7
 /** \struct TexCoord_MDL7
  *  \brief Data structure for an UV coordinate in the 3DGS MDL7 format
  *  \brief Data structure for an UV coordinate in the 3DGS MDL7 format
  */
  */
-struct TexCoord_MDL7
-{
+struct TexCoord_MDL7 {
     //! position, horizontally in range 0..1
     //! position, horizontally in range 0..1
     float u;
     float u;
 
 
     //! position, vertically in range 0..1
     //! position, vertically in range 0..1
     float v;
     float v;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct SkinSet_MDL7
 /** \struct SkinSet_MDL7
@@ -532,7 +510,7 @@ struct SkinSet_MDL7
 
 
     //! Material index
     //! Material index
     int32_t     material;    // size 4
     int32_t     material;    // size 4
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Triangle
 /** \struct Triangle
@@ -545,7 +523,7 @@ struct Triangle
 
 
     //! Vertex indices
     //! Vertex indices
     int32_t vertex[3];
     int32_t vertex[3];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Triangle_MDL3
 /** \struct Triangle_MDL3
@@ -558,7 +536,7 @@ struct Triangle_MDL3
 
 
     //! Index of 3 skin vertices in range 0..numskinverts
     //! Index of 3 skin vertices in range 0..numskinverts
     uint16_t index_uv[3];
     uint16_t index_uv[3];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Triangle_MDL7
 /** \struct Triangle_MDL7
@@ -571,7 +549,7 @@ struct Triangle_MDL7
 
 
     //! Two skinsets. The second will be used for multi-texturing
     //! Two skinsets. The second will be used for multi-texturing
     SkinSet_MDL7  skinsets[2];
     SkinSet_MDL7  skinsets[2];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV)
 #if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV)
 #   define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
 #   define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
@@ -599,7 +577,7 @@ struct Vertex
 {
 {
     uint8_t v[3];
     uint8_t v[3];
     uint8_t normalIndex;
     uint8_t normalIndex;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
@@ -625,8 +603,7 @@ struct Vertex_MDL7
         uint8_t norm162index;
         uint8_t norm162index;
         float norm[3];
         float norm[3];
     };
     };
-} PACK_STRUCT;
-
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct BoneTransform_MDL7
 /** \struct BoneTransform_MDL7
@@ -643,12 +620,11 @@ struct BoneTransform_MDL7
     //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED
     //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED
     //! THIS STUPID FILE FORMAT!
     //! THIS STUPID FILE FORMAT!
     int8_t _unused_[2];
     int8_t _unused_[2];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 #define AI_MDL7_MAX_FRAMENAMESIZE       16
 #define AI_MDL7_MAX_FRAMENAMESIZE       16
 
 
-
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Frame_MDL7
 /** \struct Frame_MDL7
  *  \brief Frame data structure used by MDL7 files
  *  \brief Frame data structure used by MDL7 files
@@ -678,7 +654,7 @@ struct SimpleFrame
 
 
     //! Vertex list of the frame
     //! Vertex list of the frame
     Vertex *verts;
     Vertex *verts;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Frame
 /** \struct Frame
@@ -691,7 +667,7 @@ struct Frame
 
 
     //! Frame data
     //! Frame data
     SimpleFrame frame;
     SimpleFrame frame;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
@@ -708,7 +684,7 @@ struct SimpleFrame_MDLn_SP
 
 
     //! Vertex list of the frame
     //! Vertex list of the frame
     Vertex_MDL4 *verts;
     Vertex_MDL4 *verts;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct GroupFrame
 /** \struct GroupFrame
@@ -730,7 +706,7 @@ struct GroupFrame
 
 
     //! List of single frames
     //! List of single frames
     SimpleFrame *frames;
     SimpleFrame *frames;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #include "./../include/assimp/Compiler/poppack1.h"
 #include "./../include/assimp/Compiler/poppack1.h"
 
 
@@ -738,8 +714,7 @@ struct GroupFrame
 /** \struct IntFace_MDL7
 /** \struct IntFace_MDL7
  *  \brief Internal data structure to temporarily represent a face
  *  \brief Internal data structure to temporarily represent a face
  */
  */
-struct IntFace_MDL7
-{
+struct IntFace_MDL7 {
     // provide a constructor for our own convenience
     // provide a constructor for our own convenience
     IntFace_MDL7()
     IntFace_MDL7()
     {
     {

+ 12 - 23
code/ObjFileParser.cpp

@@ -109,28 +109,6 @@ ObjFile::Model *ObjFileParser::GetModel() const {
     return m_pModel;
     return m_pModel;
 }
 }
 
 
-/*void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer)
-{
-    auto curPosition = buffer.begin();
-    do
-    {
-        while (*curPosition!='\n'&&*curPosition!='\\')
-        {
-            ++curPosition;
-        }
-        if (*curPosition=='\\')
-        {
-            std::vector<char> tempBuf;
-            do
-            {
-                streamBuffer.getNextDataLine(tempBuf, '\\' );
-            } while (tempBuf[0]=='\n');
-            *curPosition = ' ';
-            std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition);
-        }
-    } while (*curPosition!='\n');
-}*/
-
 void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
 void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
     // only update every 100KB or it'll be too slow
     // only update every 100KB or it'll be too slow
     //const unsigned int updateProgressEveryBytes = 100 * 1024;
     //const unsigned int updateProgressEveryBytes = 100 * 1024;
@@ -201,7 +179,18 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
 
 
         case 'u': // Parse a material desc. setter
         case 'u': // Parse a material desc. setter
             {
             {
-                getMaterialDesc();
+                std::string name;
+
+                getNameNoSpace(m_DataIt, m_DataItEnd, name);
+
+                size_t nextSpace = name.find(" ");
+                if (nextSpace != std::string::npos)
+                    name = name.substr(0, nextSpace);
+
+                if(name == "usemtl")
+                {
+                    getMaterialDesc();
+                }
             }
             }
             break;
             break;
 
 

+ 4 - 4
code/OgreParsingUtils.h

@@ -91,11 +91,11 @@ static inline std::string &TrimLeft(std::string &s, bool newlines = true)
 {
 {
     if (!newlines)
     if (!newlines)
     {
     {
-        s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))));
+        s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
     }
     }
     else
     else
     {
     {
-        s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
+        s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
     }
     }
     return s;
     return s;
 }
 }
@@ -105,11 +105,11 @@ static inline std::string &TrimRight(std::string &s, bool newlines = true)
 {
 {
     if (!newlines)
     if (!newlines)
     {
     {
-        s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
+        s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(),s.end());
     }
     }
     else
     else
     {
     {
-        s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
+        s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
     }
     }
     return s;
     return s;
 }
 }

+ 1 - 1
code/OptimizeGraph.cpp

@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "OptimizeGraph.h"
 #include "OptimizeGraph.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Exceptional.h"
 #include "Exceptional.h"
 #include <stdio.h>
 #include <stdio.h>
 
 

+ 1 - 1
code/OptimizeMeshes.cpp

@@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "OptimizeMeshes.h"
 #include "OptimizeMeshes.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Exceptional.h"
 #include "Exceptional.h"
 
 
 using namespace Assimp;
 using namespace Assimp;

+ 3 - 0
code/PlyLoader.cpp

@@ -159,6 +159,9 @@ void PLYImporter::InternReadFile(const std::string& pFile,
 
 
   // Get the file-size
   // Get the file-size
   size_t fileSize = fileStream->FileSize();
   size_t fileSize = fileStream->FileSize();
+  if ( 0 == fileSize ) {
+      throw DeadlyImportError("File " + pFile + " is empty.");
+  }
 
 
   IOStreamBuffer<char> streamedBuffer(1024 * 1024);
   IOStreamBuffer<char> streamedBuffer(1024 * 1024);
   streamedBuffer.open(fileStream.get());
   streamedBuffer.open(fileStream.get());

+ 5 - 24
code/PlyParser.cpp

@@ -935,30 +935,6 @@ bool PLY::PropertyInstance::ParseValue(const char* &pCur,
   ai_assert(NULL != out);
   ai_assert(NULL != out);
   
   
   //calc element size
   //calc element size
-  unsigned int lsize = 0;
-  switch (eType)
-  {
-  case EDT_Char:
-  case EDT_UChar:
-    lsize = 1;
-    break;
-
-  case EDT_UShort:
-  case EDT_Short:
-    lsize = 2;
-    break;
-
-  case EDT_UInt:
-  case EDT_Int:
-  case EDT_Float:
-    lsize = 4;
-    break;
-
-  case EDT_Double:
-    lsize = 8;
-    break;
-  }
-
   bool ret = true;
   bool ret = true;
   switch (eType)
   switch (eType)
   {
   {
@@ -990,6 +966,7 @@ bool PLY::PropertyInstance::ParseValue(const char* &pCur,
     out->fDouble = (double)d;
     out->fDouble = (double)d;
     break;
     break;
 
 
+  case EDT_INVALID:
   default:
   default:
     ret = false;
     ret = false;
     break;
     break;
@@ -1032,6 +1009,10 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer<char> &streamBuffer,
   case EDT_Double:
   case EDT_Double:
     lsize = 8;
     lsize = 8;
     break;
     break;
+
+  case EDT_INVALID:
+  default:
+      break;
   }
   }
 
 
   //read the next file block if needed
   //read the next file block if needed

+ 1 - 1
code/PretransformVertices.cpp

@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "PretransformVertices.h"
 #include "PretransformVertices.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Exceptional.h"
 #include "Exceptional.h"
 
 
 using namespace Assimp;
 using namespace Assimp;

+ 1 - 1
code/SceneCombiner.cpp

@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *       OptimizeGraph step.
   *       OptimizeGraph step.
   */
   */
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StringUtils.h"
 #include "StringUtils.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
 #include "Hash.h"
 #include "Hash.h"

+ 2 - 1
code/StepExporter.cpp

@@ -43,12 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
 #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
+
 #include "StepExporter.h"
 #include "StepExporter.h"
 #include "ConvertToLHProcess.h"
 #include "ConvertToLHProcess.h"
 #include "Bitmap.h"
 #include "Bitmap.h"
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include <iostream>
 #include <iostream>
 #include <ctime>
 #include <ctime>
 #include <set>
 #include <set>

+ 1 - 1
code/Subdivision.cpp

@@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "Subdivision.h"
 #include "Subdivision.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "SpatialSort.h"
 #include "SpatialSort.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
 #include "Vertex.h"
 #include "Vertex.h"

+ 2 - 2
code/X3DExporter.cpp

@@ -140,7 +140,7 @@ void X3DExporter::AttrHelper_Col3DArrToString(const aiColor3D* pArray, const siz
 	AttrHelper_CommaToPoint(pTargetString);
 	AttrHelper_CommaToPoint(pTargetString);
 }
 }
 
 
-void X3DExporter::AttrHelper_Color3ToAttrList(std::list<SAttribute> pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue)
+void X3DExporter::AttrHelper_Color3ToAttrList(std::list<SAttribute>& pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue)
 {
 {
 string tstr;
 string tstr;
 
 
@@ -150,7 +150,7 @@ string tstr;
 	pList.push_back({pName, tstr});
 	pList.push_back({pName, tstr});
 }
 }
 
 
-void X3DExporter::AttrHelper_FloatToAttrList(std::list<SAttribute> pList, const string& pName, const float pValue, const float pDefaultValue)
+void X3DExporter::AttrHelper_FloatToAttrList(std::list<SAttribute>& pList, const string& pName, const float pValue, const float pDefaultValue)
 {
 {
 string tstr;
 string tstr;
 
 

+ 2 - 2
code/X3DExporter.hpp

@@ -134,7 +134,7 @@ private:
 
 
 	/// \fn void AttrHelper_FloatToAttrList(std::list<SAttribute> pList, const std::string& pName, const float pValue, const float pDefaultValue)
 	/// \fn void AttrHelper_FloatToAttrList(std::list<SAttribute> pList, const std::string& pName, const float pValue, const float pDefaultValue)
 	/// \overload void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString)
 	/// \overload void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString)
-	void AttrHelper_FloatToAttrList(std::list<SAttribute> pList, const std::string& pName, const float pValue, const float pDefaultValue);
+	void AttrHelper_FloatToAttrList(std::list<SAttribute> &pList, const std::string& pName, const float pValue, const float pDefaultValue);
 
 
 	/// \fn void AttrHelper_Color3ToAttrList(std::list<SAttribute> pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue)
 	/// \fn void AttrHelper_Color3ToAttrList(std::list<SAttribute> pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue)
 	/// Add attribute to list if value not equal to default.
 	/// Add attribute to list if value not equal to default.
@@ -142,7 +142,7 @@ private:
 	/// \param [in] pName - name of new attribute.
 	/// \param [in] pName - name of new attribute.
 	/// \param [in] pValue - value of the new attribute.
 	/// \param [in] pValue - value of the new attribute.
 	/// \param [in] pDefaultValue - default value for checking: if pValue is equal to pDefaultValue then attribute will not be added.
 	/// \param [in] pDefaultValue - default value for checking: if pValue is equal to pDefaultValue then attribute will not be added.
-	void AttrHelper_Color3ToAttrList(std::list<SAttribute> pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue);
+	void AttrHelper_Color3ToAttrList(std::list<SAttribute> &pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue);
 
 
 	/// \fn void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list<SAttribute>& pAttrList)
 	/// \fn void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list<SAttribute>& pAttrList)
 	/// Begin new XML-node element.
 	/// Begin new XML-node element.

+ 211 - 222
code/X3DImporter.cpp

@@ -52,10 +52,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // Header files, Assimp.
 // Header files, Assimp.
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/DefaultIOSystem.h>
 #include "fast_atof.h"
 #include "fast_atof.h"
+#include "FIReader.hpp"
 
 
 // Header files, stdlib.
 // Header files, stdlib.
 #include <memory>
 #include <memory>
 #include <string>
 #include <string>
+#include <iterator>
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -66,14 +68,53 @@ const aiImporterDesc X3DImporter::Description = {
 	"smalcom",
 	"smalcom",
 	"",
 	"",
 	"See documentation in source code. Chapter: Limitations.",
 	"See documentation in source code. Chapter: Limitations.",
-	aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
+	aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
 	0,
 	0,
 	0,
 	0,
 	0,
 	0,
 	0,
 	0,
-	"x3d"
+	"x3d x3db"
 };
 };
 
 
+//const std::regex X3DImporter::pattern_nws(R"([^, \t\r\n]+)");
+//const std::regex X3DImporter::pattern_true(R"(^\s*(?:true|1)\s*$)", std::regex::icase);
+
+struct WordIterator: public std::iterator<std::input_iterator_tag, const char*> {
+    static const char *whitespace;
+    const char *start_, *end_;
+    WordIterator(const char *start, const char *end): start_(start), end_(end) {
+        start_ = start + strspn(start, whitespace);
+        if (start_ >= end_) {
+            start_ = 0;
+        }
+    }
+    WordIterator(): start_(0), end_(0) {}
+    WordIterator(const WordIterator &other): start_(other.start_), end_(other.end_) {}
+    WordIterator &operator=(const WordIterator &other) {
+        start_ = other.start_;
+        end_ = other.end_;
+        return *this;
+    }
+    bool operator==(WordIterator &other) const { return start_ == other.start_; }
+    bool operator!=(WordIterator &other) const { return start_ != other.start_; }
+    WordIterator &operator++() {
+        start_ += strcspn(start_, whitespace);
+        start_ += strspn(start_, whitespace);
+        if (start_ >= end_) {
+            start_ = 0;
+        }
+        return *this;
+    }
+    WordIterator operator++(int) {
+        WordIterator result(*this);
+        ++(*this);
+        return result;
+    }
+    const char *operator*() const { return start_; }
+};
+
+const char *WordIterator::whitespace = ", \t\r\n";
+
 X3DImporter::X3DImporter()
 X3DImporter::X3DImporter()
 : NodeElement_Cur( nullptr )
 : NodeElement_Cur( nullptr )
 , mReader( nullptr ) {
 , mReader( nullptr ) {
@@ -81,7 +122,6 @@ X3DImporter::X3DImporter()
 }
 }
 
 
 X3DImporter::~X3DImporter() {
 X3DImporter::~X3DImporter() {
-    delete mReader;
     // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
     // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
     Clear();
     Clear();
 }
 }
@@ -241,7 +281,7 @@ void X3DImporter::XML_CheckNode_MustBeEmpty()
 
 
 void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
 void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
 {
 {
-    static const size_t Uns_Skip_Len = 190;
+    static const size_t Uns_Skip_Len = 192;
     const char* Uns_Skip[ Uns_Skip_Len ] = {
     const char* Uns_Skip[ Uns_Skip_Len ] = {
 	    // CAD geometry component
 	    // CAD geometry component
 	    "CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet",
 	    "CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet",
@@ -276,7 +316,7 @@ void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeNa
 	    // Navigation component
 	    // Navigation component
 	    "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup",
 	    "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup",
 	    // Networking component
 	    // Networking component
-	    "Anchor", "LoadSensor",
+	    "EXPORT", "IMPORT", "Anchor", "LoadSensor",
 	    // NURBS component
 	    // NURBS component
 	    "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
 	    "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
 	    "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
 	    "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
@@ -368,38 +408,65 @@ bool X3DImporter::XML_SearchNode(const std::string& pNodeName)
 
 
 bool X3DImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
 bool X3DImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
 {
 {
-std::string val(mReader->getAttributeValue(pAttrIdx));
-
-	if(val == "false")
-		return false;
-	else if(val == "true")
-		return true;
-	else
-		throw DeadlyImportError("Bool attribute value can contain \"false\" or \"true\" not the \"" + val + "\"");
+    auto boolValue = std::dynamic_pointer_cast<const FIBoolValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+    if (boolValue) {
+        if (boolValue->value.size() == 1) {
+            return boolValue->value.front();
+        }
+        throw DeadlyImportError("Invalid bool value");
+    }
+    else {
+        std::string val(mReader->getAttributeValue(pAttrIdx));
+
+        if(val == "false")
+            return false;
+        else if(val == "true")
+            return true;
+        else
+            throw DeadlyImportError("Bool attribute value can contain \"false\" or \"true\" not the \"" + val + "\"");
+    }
 }
 }
 
 
 float X3DImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
 float X3DImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
 {
 {
-    std::string val;
-    float tvalf;
+    auto floatValue = std::dynamic_pointer_cast<const FIFloatValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+    if (floatValue) {
+        if (floatValue->value.size() == 1) {
+            return floatValue->value.front();
+        }
+        throw DeadlyImportError("Invalid float value");
+    }
+    else {
+        std::string val;
+        float tvalf;
 
 
-	ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
-	fast_atoreal_move(val.c_str(), tvalf, false);
+        ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
+        fast_atoreal_move(val.c_str(), tvalf, false);
 
 
-	return tvalf;
+        return tvalf;
+    }
 }
 }
 
 
 int32_t X3DImporter::XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx)
 int32_t X3DImporter::XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx)
 {
 {
-	return strtol10(mReader->getAttributeValue(pAttrIdx));
+    auto intValue = std::dynamic_pointer_cast<const FIIntValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+    if (intValue) {
+        if (intValue->value.size() == 1) {
+            return intValue->value.front();
+        }
+        throw DeadlyImportError("Invalid int value");
+    }
+    else {
+        return strtol10(mReader->getAttributeValue(pAttrIdx));
+    }
 }
 }
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue)
 {
 {
-    std::list<float> tlist;
-    std::list<float>::iterator it;
+    std::vector<float> tlist;
+    std::vector<float>::iterator it;
 
 
-	XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);
+	XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);
 	if(tlist.size() != 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 	if(tlist.size() != 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 
 
 	it = tlist.begin();
 	it = tlist.begin();
@@ -410,10 +477,10 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D&
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue)
 {
 {
-    std::list<float> tlist;
-    std::list<float>::iterator it;
+    std::vector<float> tlist;
+    std::vector<float>::iterator it;
 
 
-	XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);
+	XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);
 	if(tlist.size() != 2) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 	if(tlist.size() != 2) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 
 
 	it = tlist.begin();
 	it = tlist.begin();
@@ -423,10 +490,10 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue)
 {
 {
-    std::list<float> tlist;
-    std::list<float>::iterator it;
+    std::vector<float> tlist;
+    std::vector<float>::iterator it;
 
 
-	XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);
+	XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);
 	if(tlist.size() != 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 	if(tlist.size() != 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 
 
 	it = tlist.begin();
 	it = tlist.begin();
@@ -435,181 +502,95 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D
 	pValue.z = *it;
 	pValue.z = *it;
 }
 }
 
 
-void X3DImporter::XML_ReadNode_GetAttrVal_AsListB(const int pAttrIdx, std::list<bool>& pValue)
-{
-	// make copy of attribute value - string with list of bool values. Also all bool values is strings.
-	size_t tok_str_len = strlen(mReader->getAttributeValue(pAttrIdx));
-    if ( 0 == tok_str_len ) {
-        Throw_IncorrectAttrValue( mReader->getAttributeName( pAttrIdx ) );
-    }
-
-	tok_str_len++;// take in account terminating '\0'.
-	char *tok_str = new char[tok_str_len];
-
-	strcpy(tok_str, mReader->getAttributeValue(pAttrIdx));
-	// change all spacebars to symbol '\0'. That is needed for parsing.
-	for(size_t i = 0; i < tok_str_len; i++)
-	{
-		if(tok_str[i] == ' ') tok_str[i] = 0;
-	}
-
-	// at now check what current token is
-	for(char *tok_cur = tok_str, *tok_end = (tok_str + tok_str_len); tok_cur < tok_end;)
-	{
-		if(strncmp(tok_cur, "true", 4) == 0)
-		{
-			pValue.push_back(true);
-			tok_cur += 5;// five, not four. Because '\0' must be skipped too.
-		}
-		else if(strncmp(tok_cur, "false", 5) == 0)
-		{
-			pValue.push_back(true);
-			tok_cur += 6;// six, not five. Because '\0' must be skipped too.
-		}
-		else
-		{
-			Throw_IncorrectAttrValue(mReader->getAttributeName(pAttrIdx));
-		}
-	}// for(char* tok_cur = tok_str, tok_end = (tok_str + tok_str_len); tok_cur < tok_end;)
-
-	// delete temporary string
-	delete [] tok_str;
-}
-
 void X3DImporter::XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue)
 {
 {
-    std::list<bool> tlist;
-
-	XML_ReadNode_GetAttrVal_AsListB(pAttrIdx, tlist);// read as list
-	// and copy to array
-	if(tlist.size() > 0)
-	{
-		pValue.reserve(tlist.size());
-		for(std::list<bool>::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it);
-	}
-}
-
-void X3DImporter::XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list<int32_t>& pValue)
-{
-    const char* tstr = mReader->getAttributeValue(pAttrIdx);
-    const char* tstr_end = tstr + strlen(tstr);
-
-	do
-	{
-		const char* ostr;
-
-		int32_t tval32;
-
-		tval32 = strtol10(tstr, &ostr);
-		if(ostr == tstr) break;
+    auto boolValue = std::dynamic_pointer_cast<const FIBoolValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+    if (boolValue) {
+        pValue = boolValue->value;
+    }
+    else {
+        const char *val = mReader->getAttributeValue(pAttrIdx);
+        pValue.clear();
 
 
-		while((ostr < tstr_end) && (*ostr == ' ')) ostr++;// skip spaces between values.
+        //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws);
+        //const std::cregex_iterator wordItEnd;
+        //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::regex_match(match.str(), pattern_true); });
 
 
-		tstr = ostr;
-		pValue.push_back(tval32);
-	} while(tstr < tstr_end);
+        WordIterator wordItBegin(val, val + strlen(val));
+        WordIterator wordItEnd;
+        std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return (::tolower(match[0]) == 't') || (match[0] == '1'); });
+    }
 }
 }
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue)
 {
 {
-    std::list<int32_t> tlist;
-
-	XML_ReadNode_GetAttrVal_AsListI32(pAttrIdx, tlist);// read as list
-	// and copy to array
-	if(tlist.size() > 0)
-	{
-		pValue.reserve(tlist.size());
-		for(std::list<int32_t>::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it);
-	}
-}
-
-void X3DImporter::XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list<float>& pValue)
-{
-    std::string str_fixed;
-
-	// at first check string values like '.xxx'.
-	ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), str_fixed);
-	if(!str_fixed.size()) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
-
-	// and convert all values and place it in list.
-	const char* pstr = str_fixed.c_str();
-	const char* pstr_end = pstr + str_fixed.size();
-
-	do
-	{
-		float tvalf;
+    auto intValue = std::dynamic_pointer_cast<const FIIntValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+    if (intValue) {
+        pValue = intValue->value;
+    }
+    else {
+        const char *val = mReader->getAttributeValue(pAttrIdx);
+        pValue.clear();
 
 
-		while((*pstr == ' ') && (pstr < pstr_end)) pstr++;// skip spaces between values.
+        //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws);
+        //const std::cregex_iterator wordItEnd;
+        //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stoi(match.str()); });
 
 
-		if(pstr < pstr_end)// additional check, because attribute value can be ended with spaces.
-		{
-			pstr = fast_atoreal_move(pstr, tvalf, false);
-			pValue.push_back(tvalf);
-		}
-	} while(pstr < pstr_end);
+        WordIterator wordItBegin(val, val + strlen(val));
+        WordIterator wordItEnd;
+        std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atoi(match); });
+    }
 }
 }
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue)
 {
 {
-    std::list<float> tlist;
-
-	XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list
-	// and copy to array
-	if(tlist.size() > 0)
-	{
-		pValue.reserve(tlist.size());
-		for(std::list<float>::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it);
-	}
-}
-
-void X3DImporter::XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list<double>& pValue)
-{
-    std::string str_fixed;
-
-	// at first check string values like '.xxx'.
-	ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), str_fixed);
-	if(!str_fixed.size()) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
-
-	// and convert all values and place it in list.
-	const char* pstr = str_fixed.c_str();
-	const char* pstr_end = pstr + str_fixed.size();
-
-	do
-	{
-		double tvald;
+    auto floatValue = std::dynamic_pointer_cast<const FIFloatValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+    if (floatValue) {
+        pValue = floatValue->value;
+    }
+    else {
+        const char *val = mReader->getAttributeValue(pAttrIdx);
+        pValue.clear();
 
 
-		while((*pstr == ' ') && (pstr < pstr_end)) pstr++;// skip spaces between values.
+        //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws);
+        //const std::cregex_iterator wordItEnd;
+        //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stof(match.str()); });
 
 
-		if(pstr < pstr_end)// additional check, because attribute value can be ended with spaces.
-		{
-			pstr = fast_atoreal_move(pstr, tvald, false);
-			pValue.push_back(tvald);
-		}
-	} while(pstr < pstr_end);
+        WordIterator wordItBegin(val, val + strlen(val));
+        WordIterator wordItEnd;
+        std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atof(match); });
+    }
 }
 }
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue)
 {
 {
-    std::list<double> tlist;
+    auto doubleValue = std::dynamic_pointer_cast<const FIDoubleValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+    if (doubleValue) {
+        pValue = doubleValue->value;
+    }
+    else {
+        const char *val = mReader->getAttributeValue(pAttrIdx);
+        pValue.clear();
 
 
-	XML_ReadNode_GetAttrVal_AsListD(pAttrIdx, tlist);// read as list
-	// and copy to array
-	if(tlist.size() > 0)
-	{
-		pValue.reserve(tlist.size());
-		for(std::list<double>::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it);
-	}
+        //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws);
+        //const std::cregex_iterator wordItEnd;
+        //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stod(match.str()); });
+
+        WordIterator wordItBegin(val, val + strlen(val));
+        WordIterator wordItEnd;
+        std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atof(match); });
+    }
 }
 }
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list<aiColor3D>& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list<aiColor3D>& pValue)
 {
 {
-    std::list<float> tlist;
+    std::vector<float> tlist;
 
 
-	XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list
+	XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list
 	if(tlist.size() % 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 	if(tlist.size() % 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 
 
 	// copy data to array
 	// copy data to array
-	for(std::list<float>::iterator it = tlist.begin(); it != tlist.end();)
+	for(std::vector<float>::iterator it = tlist.begin(); it != tlist.end();)
 	{
 	{
 		aiColor3D tcol;
 		aiColor3D tcol;
 
 
@@ -635,13 +616,13 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::ve
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue)
 {
 {
-    std::list<float> tlist;
+    std::vector<float> tlist;
 
 
-	XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list
+	XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list
 	if(tlist.size() % 4) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 	if(tlist.size() % 4) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
 
 
 	// copy data to array
 	// copy data to array
-	for(std::list<float>::iterator it = tlist.begin(); it != tlist.end();)
+	for(std::vector<float>::iterator it = tlist.begin(); it != tlist.end();)
 	{
 	{
 		aiColor4D tcol;
 		aiColor4D tcol;
 
 
@@ -671,16 +652,16 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::ve
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue)
 {
 {
-    std::list<float> tlist;
+    std::vector<float> tlist;
 
 
-	XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list
+	XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list
     if ( tlist.size() % 2 )
     if ( tlist.size() % 2 )
     {
     {
         Throw_ConvertFail_Str2ArrF( mReader->getAttributeValue( pAttrIdx ) );
         Throw_ConvertFail_Str2ArrF( mReader->getAttributeValue( pAttrIdx ) );
     }
     }
 
 
 	// copy data to array
 	// copy data to array
-	for(std::list<float>::iterator it = tlist.begin(); it != tlist.end();)
+	for(std::vector<float>::iterator it = tlist.begin(); it != tlist.end();)
 	{
 	{
 		aiVector2D tvec;
 		aiVector2D tvec;
 
 
@@ -708,16 +689,16 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::ve
 
 
 void X3DImporter::XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue)
 void X3DImporter::XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue)
 {
 {
-    std::list<float> tlist;
+    std::vector<float> tlist;
 
 
-	XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list
+	XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list
     if ( tlist.size() % 3 )
     if ( tlist.size() % 3 )
     {
     {
         Throw_ConvertFail_Str2ArrF( mReader->getAttributeValue( pAttrIdx ) );
         Throw_ConvertFail_Str2ArrF( mReader->getAttributeValue( pAttrIdx ) );
     }
     }
 
 
 	// copy data to array
 	// copy data to array
-	for(std::list<float>::iterator it = tlist.begin(); it != tlist.end();)
+	for(std::vector<float>::iterator it = tlist.begin(); it != tlist.end();)
 	{
 	{
 		aiVector3D tvec;
 		aiVector3D tvec;
 
 
@@ -907,9 +888,9 @@ void X3DImporter::GeometryHelper_MakeQL_RectParallelepiped(const aiVector3D& pSi
 
 
 #undef MESH_RectParallelepiped_CREATE_VERT
 #undef MESH_RectParallelepiped_CREATE_VERT
 
 
-void X3DImporter::GeometryHelper_CoordIdxStr2FacesArr(const std::list<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const
+void X3DImporter::GeometryHelper_CoordIdxStr2FacesArr(const std::vector<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const
 {
 {
-    std::list<int32_t> f_data(pCoordIdx);
+    std::vector<int32_t> f_data(pCoordIdx);
     std::vector<unsigned int> inds;
     std::vector<unsigned int> inds;
     unsigned int prim_type = 0;
     unsigned int prim_type = 0;
 
 
@@ -922,7 +903,7 @@ void X3DImporter::GeometryHelper_CoordIdxStr2FacesArr(const std::list<int32_t>&
 	pFaces.reserve(f_data.size() / 3);
 	pFaces.reserve(f_data.size() / 3);
 	inds.reserve(4);
 	inds.reserve(4);
     //PrintVectorSet("build. ci", pCoordIdx);
     //PrintVectorSet("build. ci", pCoordIdx);
-	for(std::list<int32_t>::iterator it = f_data.begin(); it != f_data.end(); it++)
+	for(std::vector<int32_t>::iterator it = f_data.begin(); it != f_data.end(); it++)
 	{
 	{
 		// when face is got count how many indices in it.
 		// when face is got count how many indices in it.
 		if(*it == (-1))
 		if(*it == (-1))
@@ -1014,7 +995,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D
 	}// if(pColorPerVertex) else
 	}// if(pColorPerVertex) else
 }
 }
 
 
-void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx,
+void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
 										const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const
 										const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const
 {
 {
     std::list<aiColor4D> tcol;
     std::list<aiColor4D> tcol;
@@ -1029,7 +1010,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>&
 	MeshGeometry_AddColor(pMesh, pCoordIdx, pColorIdx, tcol, pColorPerVertex);
 	MeshGeometry_AddColor(pMesh, pCoordIdx, pColorIdx, tcol, pColorPerVertex);
 }
 }
 
 
-void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx,
+void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
 										const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
 										const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
 {
 {
     std::vector<aiColor4D> col_tgt_arr;
     std::vector<aiColor4D> col_tgt_arr;
@@ -1060,7 +1041,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>&
 			}
 			}
 			// create list with colors for every vertex.
 			// create list with colors for every vertex.
 			col_tgt_arr.resize(pMesh.mNumVertices);
 			col_tgt_arr.resize(pMesh.mNumVertices);
-			for(std::list<int32_t>::const_iterator colidx_it = pColorIdx.begin(), coordidx_it = pCoordIdx.begin(); colidx_it != pColorIdx.end(); colidx_it++, coordidx_it++)
+			for(std::vector<int32_t>::const_iterator colidx_it = pColorIdx.begin(), coordidx_it = pCoordIdx.begin(); colidx_it != pColorIdx.end(); colidx_it++, coordidx_it++)
 			{
 			{
                 if ( *colidx_it == ( -1 ) )
                 if ( *colidx_it == ( -1 ) )
                 {
                 {
@@ -1108,7 +1089,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>&
 			// create list with colors for every vertex using faces indices.
 			// create list with colors for every vertex using faces indices.
 			col_tgt_arr.resize(pMesh.mNumFaces);
 			col_tgt_arr.resize(pMesh.mNumFaces);
 
 
-			std::list<int32_t>::const_iterator colidx_it = pColorIdx.begin();
+			std::vector<int32_t>::const_iterator colidx_it = pColorIdx.begin();
 			for(size_t fi = 0; fi < pMesh.mNumFaces; fi++)
 			for(size_t fi = 0; fi < pMesh.mNumFaces; fi++)
 			{
 			{
 				if((unsigned int)*colidx_it > pMesh.mNumFaces) throw DeadlyImportError("MeshGeometry_AddColor2. Face idx is out of range.");
 				if((unsigned int)*colidx_it > pMesh.mNumFaces) throw DeadlyImportError("MeshGeometry_AddColor2. Face idx is out of range.");
@@ -1138,7 +1119,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>&
 	MeshGeometry_AddColor(pMesh, col_tgt_list, pColorPerVertex);
 	MeshGeometry_AddColor(pMesh, col_tgt_list, pColorPerVertex);
 }
 }
 
 
-void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pNormalIdx,
+void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pNormalIdx,
 								const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const
 								const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const
 {
 {
     std::vector<size_t> tind;
     std::vector<size_t> tind;
@@ -1153,35 +1134,36 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<int32_t>
 
 
 	if(pNormalPerVertex)
 	if(pNormalPerVertex)
 	{
 	{
-		const std::list<int32_t>* srcidx;
-
 		if(pNormalIdx.size() > 0)
 		if(pNormalIdx.size() > 0)
 		{
 		{
 			// check indices array count.
 			// check indices array count.
 			if(pNormalIdx.size() != pCoordIdx.size()) throw DeadlyImportError("Normals and Coords inidces count must be equal.");
 			if(pNormalIdx.size() != pCoordIdx.size()) throw DeadlyImportError("Normals and Coords inidces count must be equal.");
 
 
-			srcidx = &pNormalIdx;
-		}
-		else
-		{
-			srcidx = &pCoordIdx;
-		}
+			tind.reserve(pNormalIdx.size());
+			for(std::vector<int32_t>::const_iterator it = pNormalIdx.begin(); it != pNormalIdx.end(); it++)
+			{
+				if(*it != (-1)) tind.push_back(*it);
+			}
 
 
-		tind.reserve(srcidx->size());
-		for(std::list<int32_t>::const_iterator it = srcidx->begin(); it != srcidx->end(); it++)
-		{
-			if(*it != (-1)) tind.push_back(*it);
-		}
+			// copy normals to mesh
+			pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
+			for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++)
+			{
+				if(tind[i] >= norm_arr_copy.size())
+					throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) +
+											") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + ".");
 
 
-		// copy normals to mesh
-		pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
-		for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++)
+				pMesh.mNormals[i] = norm_arr_copy[tind[i]];
+			}
+		}
+		else
 		{
 		{
-			if(tind[i] >= norm_arr_copy.size())
-				throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) +
-										") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + ".");
+			if(pNormals.size() != pMesh.mNumVertices) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and vertices count must be equal.");
 
 
-			pMesh.mNormals[i] = norm_arr_copy[tind[i]];
+			// copy normals to mesh
+			pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
+			std::list<aiVector3D>::const_iterator norm_it = pNormals.begin();
+			for(size_t i = 0; i < pMesh.mNumVertices; i++) pMesh.mNormals[i] = *norm_it++;
 		}
 		}
 	}// if(pNormalPerVertex)
 	}// if(pNormalPerVertex)
 	else
 	else
@@ -1190,7 +1172,7 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<int32_t>
 		{
 		{
 			if(pMesh.mNumFaces != pNormalIdx.size()) throw DeadlyImportError("Normals faces count must be equal to mesh faces count.");
 			if(pMesh.mNumFaces != pNormalIdx.size()) throw DeadlyImportError("Normals faces count must be equal to mesh faces count.");
 
 
-			std::list<int32_t>::const_iterator normidx_it = pNormalIdx.begin();
+			std::vector<int32_t>::const_iterator normidx_it = pNormalIdx.begin();
 
 
 			tind.reserve(pNormalIdx.size());
 			tind.reserve(pNormalIdx.size());
 			for(size_t i = 0, i_e = pNormalIdx.size(); i < i_e; i++) tind.push_back(*normidx_it++);
 			for(size_t i = 0, i_e = pNormalIdx.size(); i < i_e; i++) tind.push_back(*normidx_it++);
@@ -1243,7 +1225,7 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector
 	}// if(pNormalPerVertex) else
 	}// if(pNormalPerVertex) else
 }
 }
 
 
-void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pTexCoordIdx,
+void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pTexCoordIdx,
 								const std::list<aiVector2D>& pTexCoords) const
 								const std::list<aiVector2D>& pTexCoords) const
 {
 {
     std::vector<aiVector3D> texcoord_arr_copy;
     std::vector<aiVector3D> texcoord_arr_copy;
@@ -1316,7 +1298,7 @@ void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<aiVect
     }
     }
 }
 }
 
 
-aiMesh* X3DImporter::GeometryHelper_MakeMesh(const std::list<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const
+aiMesh* X3DImporter::GeometryHelper_MakeMesh(const std::vector<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const
 {
 {
     std::vector<aiFace> faces;
     std::vector<aiFace> faces;
     unsigned int prim_type = 0;
     unsigned int prim_type = 0;
@@ -1419,9 +1401,12 @@ void X3DImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::s
 	}
 	}
 }
 }
 
 
+extern FIVocabulary X3D_vocabulary_3_2;
+extern FIVocabulary X3D_vocabulary_3_3;
+
 void X3DImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
 void X3DImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
 {
 {
-    irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
+    std::unique_ptr<FIReader> OldReader = std::move(mReader);// store current XMLreader.
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
 
 	// Check whether we can read from the file
 	// Check whether we can read from the file
@@ -1429,19 +1414,18 @@ void X3DImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
     {
     {
         throw DeadlyImportError( "Failed to open X3D file " + pFile + "." );
         throw DeadlyImportError( "Failed to open X3D file " + pFile + "." );
     }
     }
-	// generate a XML reader for it
-	std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
-	mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
+	mReader = FIReader::create(file.get());
     if ( !mReader )
     if ( !mReader )
     {
     {
         throw DeadlyImportError( "Failed to create XML reader for file" + pFile + "." );
         throw DeadlyImportError( "Failed to create XML reader for file" + pFile + "." );
     }
     }
+    mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.2", &X3D_vocabulary_3_2);
+    mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.3", &X3D_vocabulary_3_3);
 	// start reading
 	// start reading
 	ParseNode_Root();
 	ParseNode_Root();
 
 
-	delete mReader;
 	// restore old XMLreader
 	// restore old XMLreader
-	mReader = OldReader;
+	mReader = std::move(OldReader);
 }
 }
 
 
 void X3DImporter::ParseNode_Root()
 void X3DImporter::ParseNode_Root()
@@ -1655,7 +1639,7 @@ bool X3DImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool p
 {
 {
     const std::string extension = GetExtension(pFile);
     const std::string extension = GetExtension(pFile);
 
 
-	if(extension == "x3d") return true;
+	if((extension == "x3d") || (extension == "x3db")) return true;
 
 
 	if(!extension.length() || pCheckSig)
 	if(!extension.length() || pCheckSig)
 	{
 	{
@@ -1670,6 +1654,7 @@ bool X3DImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool p
 void X3DImporter::GetExtensionList(std::set<std::string>& pExtensionList)
 void X3DImporter::GetExtensionList(std::set<std::string>& pExtensionList)
 {
 {
 	pExtensionList.insert("x3d");
 	pExtensionList.insert("x3d");
+	pExtensionList.insert("x3db");
 }
 }
 
 
 const aiImporterDesc* X3DImporter::GetInfo () const
 const aiImporterDesc* X3DImporter::GetInfo () const
@@ -1679,9 +1664,13 @@ const aiImporterDesc* X3DImporter::GetInfo () const
 
 
 void X3DImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
 void X3DImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
 {
 {
+	mpIOHandler = pIOHandler;
+
 	Clear();// delete old graph.
 	Clear();// delete old graph.
-	mFileDir = DefaultIOSystem::absolutePath(pFile);
+	std::string::size_type slashPos = pFile.find_last_of("\\/");
+	pIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : pFile.substr(0, slashPos + 1));
 	ParseFile(pFile, pIOHandler);
 	ParseFile(pFile, pIOHandler);
+	pIOHandler->PopDirectory();
 	//
 	//
 	// Assimp use static arrays of objects for fast speed of rendering. That's good, but need some additional operations/
 	// Assimp use static arrays of objects for fast speed of rendering. That's good, but need some additional operations/
 	// We know that geometry objects(meshes) are stored in <Shape>, also in <Shape>-><Appearance> materials(in Assimp logical view)
 	// We know that geometry objects(meshes) are stored in <Shape>, also in <Shape>-><Appearance> materials(in Assimp logical view)

+ 14 - 21
code/X3DImporter.hpp

@@ -56,6 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/types.h>
 #include <assimp/types.h>
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 #include "irrXMLWrapper.h"
 #include "irrXMLWrapper.h"
+#include "FIReader.hpp"
+//#include <regex>
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -101,7 +103,7 @@ namespace Assimp {
 ///		Navigation component:
 ///		Navigation component:
 ///			"Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup"
 ///			"Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup"
 ///		Networking component:
 ///		Networking component:
-///			"Anchor", "LoadSensor"
+///			"EXPORT", "IMPORT", "Anchor", "LoadSensor"
 ///		NURBS component:
 ///		NURBS component:
 ///			"Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
 ///			"Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
 ///			"NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
 ///			"NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
@@ -449,33 +451,21 @@ private:
 	/// Read attribute value.
 	/// Read attribute value.
 	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
 	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
 	/// \param [out] pValue - read data.
 	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListB(const int pAttrIdx, std::list<bool>& pValue);
-
-	/// \overload void XML_ReadNode_GetAttrVal_AsListBool(const int pAttrIdx, std::list<bool>& pValue)
 	void XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue);
 	void XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue);
 
 
 	/// Read attribute value.
 	/// Read attribute value.
 	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
 	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
 	/// \param [out] pValue - read data.
 	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list<int32_t>& pValue);
-
-	/// \overload void XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list<int32_t>& pValue)
 	void XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue);
 	void XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue);
 
 
 	/// Read attribute value.
 	/// Read attribute value.
 	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
 	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
 	/// \param [out] pValue - read data.
 	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list<float>& pValue);
-
-    /// \overload void XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list<float>& pValue)
 	void XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue);
 	void XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue);
 
 
     /// Read attribute value.
     /// Read attribute value.
 	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
 	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
 	/// \param [out] pValue - read data.
 	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list<double>& pValue);
-
-	/// \overload void XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list<double>& pValue)
 	void XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue);
 	void XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue);
 
 
 	/// Read attribute value.
 	/// Read attribute value.
@@ -554,7 +544,7 @@ private:
 	/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
 	/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
 	/// \param [in] pFaces - created faces array.
 	/// \param [in] pFaces - created faces array.
 	/// \param [in] pPrimitiveTypes - type of primitives in faces.
 	/// \param [in] pPrimitiveTypes - type of primitives in faces.
-	void GeometryHelper_CoordIdxStr2FacesArr(const std::list<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const;
+	void GeometryHelper_CoordIdxStr2FacesArr(const std::vector<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const;
 
 
 	/// Add colors to mesh.
 	/// Add colors to mesh.
 	/// a. If colorPerVertex is FALSE, colours are applied to each face, as follows:
 	/// a. If colorPerVertex is FALSE, colours are applied to each face, as follows:
@@ -573,11 +563,11 @@ private:
 	/// then pColorIdx contain color indices for every faces and must not contain delimiter "-1".
 	/// then pColorIdx contain color indices for every faces and must not contain delimiter "-1".
 	/// \param [in] pColors - defined colors.
 	/// \param [in] pColors - defined colors.
 	/// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
 	/// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
-	void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx,
+	void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
 								const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
 								const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
 
 
 	/// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
 	/// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
-	void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx,
+	void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
 								const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
 								const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
 
 
 	/// Add colors to mesh.
 	/// Add colors to mesh.
@@ -590,14 +580,14 @@ private:
 	void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
 	void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
 
 
 	/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
 	/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
-	void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pNormalIdx,
+	void MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pNormalIdx,
 								const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
 								const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
 
 
 	/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
 	/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
 	void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
 	void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
 
 
     /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
     /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
-	void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pTexCoordIdx,
+	void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pTexCoordIdx,
 								const std::list<aiVector2D>& pTexCoords) const;
 								const std::list<aiVector2D>& pTexCoords) const;
 
 
     /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
     /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
@@ -607,7 +597,7 @@ private:
 	/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
 	/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
 	/// \param [in] pVertices - vertices of mesh.
 	/// \param [in] pVertices - vertices of mesh.
 	/// \return created mesh.
 	/// \return created mesh.
-	aiMesh* GeometryHelper_MakeMesh(const std::list<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const;
+	aiMesh* GeometryHelper_MakeMesh(const std::vector<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const;
 
 
 	/***********************************************/
 	/***********************************************/
 	/******** Functions: parse set private *********/
 	/******** Functions: parse set private *********/
@@ -826,13 +816,16 @@ private:
     /****************** Constants ******************/
     /****************** Constants ******************/
     /***********************************************/
     /***********************************************/
     static const aiImporterDesc Description;
     static const aiImporterDesc Description;
+    //static const std::regex pattern_nws;
+    //static const std::regex pattern_true;
+
 
 
     /***********************************************/
     /***********************************************/
     /****************** Variables ******************/
     /****************** Variables ******************/
     /***********************************************/
     /***********************************************/
     CX3DImporter_NodeElement* NodeElement_Cur;///< Current element.
     CX3DImporter_NodeElement* NodeElement_Cur;///< Current element.
-    irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
-    std::string mFileDir;
+    std::unique_ptr<FIReader> mReader;///< Pointer to XML-reader object
+    IOSystem *mpIOHandler;
 };// class X3DImporter
 };// class X3DImporter
 
 
 }// namespace Assimp
 }// namespace Assimp

+ 11 - 11
code/X3DImporter_Geometry3D.cpp

@@ -285,7 +285,7 @@ void X3DImporter::ParseNode_Geometry3D_ElevationGrid()
     bool ccw = true;
     bool ccw = true;
     bool colorPerVertex = true;
     bool colorPerVertex = true;
     float creaseAngle = 0;
     float creaseAngle = 0;
-    std::list<float> height;
+    std::vector<float> height;
     bool normalPerVertex = true;
     bool normalPerVertex = true;
     bool solid = true;
     bool solid = true;
     int32_t xDimension = 0;
     int32_t xDimension = 0;
@@ -301,7 +301,7 @@ void X3DImporter::ParseNode_Geometry3D_ElevationGrid()
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
 		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsListF);
+		MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsArrF);
 		MACRO_ATTRREAD_CHECK_RET("xDimension", xDimension, XML_ReadNode_GetAttrVal_AsI32);
 		MACRO_ATTRREAD_CHECK_RET("xDimension", xDimension, XML_ReadNode_GetAttrVal_AsI32);
 		MACRO_ATTRREAD_CHECK_RET("xSpacing", xSpacing, XML_ReadNode_GetAttrVal_AsFloat);
 		MACRO_ATTRREAD_CHECK_RET("xSpacing", xSpacing, XML_ReadNode_GetAttrVal_AsFloat);
 		MACRO_ATTRREAD_CHECK_RET("zDimension", zDimension, XML_ReadNode_GetAttrVal_AsI32);
 		MACRO_ATTRREAD_CHECK_RET("zDimension", zDimension, XML_ReadNode_GetAttrVal_AsI32);
@@ -326,7 +326,7 @@ void X3DImporter::ParseNode_Geometry3D_ElevationGrid()
 		CX3DImporter_NodeElement_ElevationGrid& grid_alias = *((CX3DImporter_NodeElement_ElevationGrid*)ne);// create alias for conveience
 		CX3DImporter_NodeElement_ElevationGrid& grid_alias = *((CX3DImporter_NodeElement_ElevationGrid*)ne);// create alias for conveience
 
 
 		{// create grid vertices list
 		{// create grid vertices list
-			std::list<float>::const_iterator he_it = height.begin();
+			std::vector<float>::const_iterator he_it = height.begin();
 
 
 			for(int32_t zi = 0; zi < zDimension; zi++)// rows
 			for(int32_t zi = 0; zi < zDimension; zi++)// rows
 			{
 			{
@@ -863,29 +863,29 @@ void X3DImporter::ParseNode_Geometry3D_IndexedFaceSet()
 {
 {
     std::string use, def;
     std::string use, def;
     bool ccw = true;
     bool ccw = true;
-    std::list<int32_t> colorIndex;
+    std::vector<int32_t> colorIndex;
     bool colorPerVertex = true;
     bool colorPerVertex = true;
     bool convex = true;
     bool convex = true;
-    std::list<int32_t> coordIndex;
+    std::vector<int32_t> coordIndex;
     float creaseAngle = 0;
     float creaseAngle = 0;
-    std::list<int32_t> normalIndex;
+    std::vector<int32_t> normalIndex;
     bool normalPerVertex = true;
     bool normalPerVertex = true;
     bool solid = true;
     bool solid = true;
-    std::list<int32_t> texCoordIndex;
+    std::vector<int32_t> texCoordIndex;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
 
 
 	MACRO_ATTRREAD_LOOPBEG;
 	MACRO_ATTRREAD_LOOPBEG;
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
 		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
 
 
 	// if "USE" defined then find already defined element.
 	// if "USE" defined then find already defined element.

+ 8 - 8
code/X3DImporter_Metadata.cpp

@@ -123,14 +123,14 @@ void X3DImporter::ParseNode_MetadataBoolean()
 {
 {
     std::string def, use;
     std::string def, use;
     std::string name, reference;
     std::string name, reference;
-    std::list<bool> value;
+    std::vector<bool> value;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
 
 
 	MACRO_ATTRREAD_LOOPBEG;
 	MACRO_ATTRREAD_LOOPBEG;
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListB);
+		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrB);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
 
 
 	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaBoolean, "MetadataBoolean", ENET_MetaBoolean);
 	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaBoolean, "MetadataBoolean", ENET_MetaBoolean);
@@ -147,14 +147,14 @@ void X3DImporter::ParseNode_MetadataDouble()
 {
 {
     std::string def, use;
     std::string def, use;
     std::string name, reference;
     std::string name, reference;
-    std::list<double> value;
+    std::vector<double> value;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
 
 
 	MACRO_ATTRREAD_LOOPBEG;
 	MACRO_ATTRREAD_LOOPBEG;
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListD);
+		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrD);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
 
 
 	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaDouble, "MetadataDouble", ENET_MetaDouble);
 	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaDouble, "MetadataDouble", ENET_MetaDouble);
@@ -171,14 +171,14 @@ void X3DImporter::ParseNode_MetadataFloat()
 {
 {
     std::string def, use;
     std::string def, use;
     std::string name, reference;
     std::string name, reference;
-    std::list<float> value;
+    std::vector<float> value;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
 
 
 	MACRO_ATTRREAD_LOOPBEG;
 	MACRO_ATTRREAD_LOOPBEG;
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListF);
+		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrF);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
 
 
 	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaFloat, "MetadataFloat", ENET_MetaFloat);
 	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaFloat, "MetadataFloat", ENET_MetaFloat);
@@ -195,14 +195,14 @@ void X3DImporter::ParseNode_MetadataInteger()
 {
 {
     std::string def, use;
     std::string def, use;
     std::string name, reference;
     std::string name, reference;
-    std::list<int32_t> value;
+    std::vector<int32_t> value;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
 
 
 	MACRO_ATTRREAD_LOOPBEG;
 	MACRO_ATTRREAD_LOOPBEG;
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
 		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrI32);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
 
 
 	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaInteger, "MetadataInteger", ENET_MetaInteger);
 	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaInteger, "MetadataInteger", ENET_MetaInteger);

+ 28 - 5
code/X3DImporter_Networking.cpp

@@ -51,9 +51,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // Header files, Assimp.
 // Header files, Assimp.
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/DefaultIOSystem.h>
 
 
+//#include <regex>
+
 namespace Assimp
 namespace Assimp
 {
 {
 
 
+//static std::regex pattern_parentDir(R"((^|/)[^/]+/../)");
+static std::string parentDir("/../");
+
 // <Inline
 // <Inline
 // DEF=""              ID
 // DEF=""              ID
 // USE=""              IDREF
 // USE=""              IDREF
@@ -89,12 +94,30 @@ void X3DImporter::ParseNode_Networking_Inline()
 
 
 		if(load && (url.size() > 0))
 		if(load && (url.size() > 0))
 		{
 		{
-			DefaultIOSystem io_handler;
-			std::string full_path;
-
-			full_path = mFileDir + "/" + url.front();
+			std::string full_path = mpIOHandler->CurrentDirectory() + url.front();
+
+			//full_path = std::regex_replace(full_path, pattern_parentDir, "$1");
+			for (std::string::size_type pos = full_path.find(parentDir); pos != std::string::npos; pos = full_path.find(parentDir, pos)) {
+				if (pos > 0) {
+					std::string::size_type pos2 = full_path.rfind('/', pos - 1);
+					if (pos2 != std::string::npos) {
+						full_path.erase(pos2, pos - pos2 + 3);
+						pos = pos2;
+					}
+					else {
+						full_path.erase(0, pos + 4);
+						pos = 0;
+					}
+				}
+				else {
+					pos += 3;
+				}
+			}
 			// Attribute "url" can contain list of strings. But we need only one - first.
 			// Attribute "url" can contain list of strings. But we need only one - first.
-			ParseFile(full_path, &io_handler);
+			std::string::size_type slashPos = full_path.find_last_of("\\/");
+			mpIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : full_path.substr(0, slashPos + 1));
+			ParseFile(full_path, mpIOHandler);
+			mpIOHandler->PopDirectory();
 		}
 		}
 
 
 		// check for X3DMetadataObject childs.
 		// check for X3DMetadataObject childs.

+ 14 - 13
code/X3DImporter_Node.hpp

@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 // Header files, stdlib.
 // Header files, stdlib.
 #include <list>
 #include <list>
+#include <vector>
 #include <string>
 #include <string>
 
 
 /// \class CX3DImporter_NodeElement
 /// \class CX3DImporter_NodeElement
@@ -264,7 +265,7 @@ public:
 /// This struct describe metavalue of type boolean.
 /// This struct describe metavalue of type boolean.
 struct CX3DImporter_NodeElement_MetaBoolean : public CX3DImporter_NodeElement_Meta
 struct CX3DImporter_NodeElement_MetaBoolean : public CX3DImporter_NodeElement_Meta
 {
 {
-	std::list<bool> Value;///< Stored value.
+	std::vector<bool> Value;///< Stored value.
 
 
 	/// \fn CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent)
 	/// \fn CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent)
 	/// Constructor
 	/// Constructor
@@ -279,7 +280,7 @@ struct CX3DImporter_NodeElement_MetaBoolean : public CX3DImporter_NodeElement_Me
 /// This struct describe metavalue of type double.
 /// This struct describe metavalue of type double.
 struct CX3DImporter_NodeElement_MetaDouble : public CX3DImporter_NodeElement_Meta
 struct CX3DImporter_NodeElement_MetaDouble : public CX3DImporter_NodeElement_Meta
 {
 {
-	std::list<double> Value;///< Stored value.
+	std::vector<double> Value;///< Stored value.
 
 
 	/// \fn CX3DImporter_NodeElement_MetaDouble(CX3DImporter_NodeElement* pParent)
 	/// \fn CX3DImporter_NodeElement_MetaDouble(CX3DImporter_NodeElement* pParent)
 	/// Constructor
 	/// Constructor
@@ -294,7 +295,7 @@ struct CX3DImporter_NodeElement_MetaDouble : public CX3DImporter_NodeElement_Met
 /// This struct describe metavalue of type float.
 /// This struct describe metavalue of type float.
 struct CX3DImporter_NodeElement_MetaFloat : public CX3DImporter_NodeElement_Meta
 struct CX3DImporter_NodeElement_MetaFloat : public CX3DImporter_NodeElement_Meta
 {
 {
-	std::list<float> Value;///< Stored value.
+	std::vector<float> Value;///< Stored value.
 
 
 	/// \fn CX3DImporter_NodeElement_MetaFloat(CX3DImporter_NodeElement* pParent)
 	/// \fn CX3DImporter_NodeElement_MetaFloat(CX3DImporter_NodeElement* pParent)
 	/// Constructor
 	/// Constructor
@@ -309,7 +310,7 @@ struct CX3DImporter_NodeElement_MetaFloat : public CX3DImporter_NodeElement_Meta
 /// This struct describe metavalue of type integer.
 /// This struct describe metavalue of type integer.
 struct CX3DImporter_NodeElement_MetaInteger : public CX3DImporter_NodeElement_Meta
 struct CX3DImporter_NodeElement_MetaInteger : public CX3DImporter_NodeElement_Meta
 {
 {
-	std::list<int32_t> Value;///< Stored value.
+	std::vector<int32_t> Value;///< Stored value.
 
 
 	/// \fn CX3DImporter_NodeElement_MetaInteger(CX3DImporter_NodeElement* pParent)
 	/// \fn CX3DImporter_NodeElement_MetaInteger(CX3DImporter_NodeElement* pParent)
 	/// Constructor
 	/// Constructor
@@ -508,7 +509,7 @@ public:
 	/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
 	/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
 	/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
 	/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
 	float CreaseAngle;
 	float CreaseAngle;
-	std::list<int32_t> CoordIdx;///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
+	std::vector<int32_t> CoordIdx;///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
 
 
 	/***********************************************/
 	/***********************************************/
 	/****************** Functions ******************/
 	/****************** Functions ******************/
@@ -554,21 +555,21 @@ public:
 	/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
 	/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
 	/// ccw field, results are undefined.
 	/// ccw field, results are undefined.
 	bool CCW;
 	bool CCW;
-	std::list<int32_t> ColorIndex;///< Field to specify the polygonal faces by indexing into the <Color> or <ColorRGBA>.
+	std::vector<int32_t> ColorIndex;///< Field to specify the polygonal faces by indexing into the <Color> or <ColorRGBA>.
 	bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line).
 	bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line).
 	/// \var Convex
 	/// \var Convex
 	/// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself,
 	/// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself,
 	/// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results
 	/// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results
 	/// even if the convex field is FALSE.
 	/// even if the convex field is FALSE.
 	bool Convex;
 	bool Convex;
-	std::list<int32_t> CoordIndex;///< Field to specify the polygonal faces by indexing into the <Coordinate>.
+	std::vector<int32_t> CoordIndex;///< Field to specify the polygonal faces by indexing into the <Coordinate>.
 	/// \var CreaseAngle
 	/// \var CreaseAngle
 	/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
 	/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
 	/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
 	/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
 	float CreaseAngle;
 	float CreaseAngle;
-	std::list<int32_t> NormalIndex;///< Field to specify the polygonal faces by indexing into the <Normal>.
+	std::vector<int32_t> NormalIndex;///< Field to specify the polygonal faces by indexing into the <Normal>.
 	bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line).
 	bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line).
-	std::list<int32_t> TexCoordIndex;///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
+	std::vector<int32_t> TexCoordIndex;///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
 
 
 	/***********************************************/
 	/***********************************************/
 	/****************** Functions ******************/
 	/****************** Functions ******************/
@@ -616,10 +617,10 @@ public:
 	bool CCW;
 	bool CCW;
 	bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line).
 	bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line).
 	bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line).
 	bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line).
-	std::list<int32_t> CoordIndex;///< Field to specify the polygonal faces by indexing into the <Coordinate>.
-	std::list<int32_t> NormalIndex;///< Field to specify the polygonal faces by indexing into the <Normal>.
-	std::list<int32_t> TexCoordIndex;///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
-	std::list<int32_t> VertexCount;///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
+	std::vector<int32_t> CoordIndex;///< Field to specify the polygonal faces by indexing into the <Coordinate>.
+	std::vector<int32_t> NormalIndex;///< Field to specify the polygonal faces by indexing into the <Normal>.
+	std::vector<int32_t> TexCoordIndex;///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
+	std::vector<int32_t> VertexCount;///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
 
 
 	/***********************************************/
 	/***********************************************/
 	/****************** Functions ******************/
 	/****************** Functions ******************/

+ 117 - 22
code/X3DImporter_Rendering.cpp

@@ -180,16 +180,16 @@ void X3DImporter::ParseNode_Rendering_Coordinate()
 void X3DImporter::ParseNode_Rendering_IndexedLineSet()
 void X3DImporter::ParseNode_Rendering_IndexedLineSet()
 {
 {
     std::string use, def;
     std::string use, def;
-    std::list<int32_t> colorIndex;
+    std::vector<int32_t> colorIndex;
     bool colorPerVertex = true;
     bool colorPerVertex = true;
-    std::list<int32_t> coordIndex;
+    std::vector<int32_t> coordIndex;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
 
 
 	MACRO_ATTRREAD_LOOPBEG;
 	MACRO_ATTRREAD_LOOPBEG;
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
 
 
 	// if "USE" defined then find already defined element.
 	// if "USE" defined then find already defined element.
@@ -256,7 +256,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet()
     std::string use, def;
     std::string use, def;
     bool ccw = true;
     bool ccw = true;
     bool colorPerVertex = true;
     bool colorPerVertex = true;
-    std::list<int32_t> index;
+    std::vector<int32_t> index;
     bool normalPerVertex = true;
     bool normalPerVertex = true;
     bool solid = true;
     bool solid = true;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
@@ -265,7 +265,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet()
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
@@ -288,9 +288,46 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet()
 
 
 		ne_alias.CCW = ccw;
 		ne_alias.CCW = ccw;
 		ne_alias.ColorPerVertex = colorPerVertex;
 		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.CoordIndex = index;
 		ne_alias.NormalPerVertex = normalPerVertex;
 		ne_alias.NormalPerVertex = normalPerVertex;
 		ne_alias.Solid = solid;
 		ne_alias.Solid = solid;
+
+		ne_alias.CoordIndex.clear();
+		int counter = 0;
+		int32_t idx[3];
+		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+		{
+			idx[2] = *idx_it;
+			if (idx[2] < 0)
+			{
+				counter = 0;
+			}
+			else
+			{
+				if (counter >= 2)
+				{
+					if(ccw)
+					{
+						ne_alias.CoordIndex.push_back(idx[0]);
+						ne_alias.CoordIndex.push_back(idx[1]);
+						ne_alias.CoordIndex.push_back(idx[2]);
+					}
+					else
+					{
+						ne_alias.CoordIndex.push_back(idx[0]);
+						ne_alias.CoordIndex.push_back(idx[2]);
+						ne_alias.CoordIndex.push_back(idx[1]);
+					}
+					ne_alias.CoordIndex.push_back(-1);
+					idx[1] = idx[2];
+				}
+				else
+				{
+					idx[counter] = idx[2];
+				}
+				++counter;
+			}
+		}// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
+
         // check for child nodes
         // check for child nodes
         if(!mReader->isEmptyElement())
         if(!mReader->isEmptyElement())
         {
         {
@@ -337,7 +374,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleSet()
     std::string use, def;
     std::string use, def;
     bool ccw = true;
     bool ccw = true;
     bool colorPerVertex = true;
     bool colorPerVertex = true;
-    std::list<int32_t> index;
+    std::vector<int32_t> index;
     bool normalPerVertex = true;
     bool normalPerVertex = true;
     bool solid = true;
     bool solid = true;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
@@ -346,7 +383,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleSet()
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
@@ -369,9 +406,34 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleSet()
 
 
 		ne_alias.CCW = ccw;
 		ne_alias.CCW = ccw;
 		ne_alias.ColorPerVertex = colorPerVertex;
 		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.CoordIndex = index;
 		ne_alias.NormalPerVertex = normalPerVertex;
 		ne_alias.NormalPerVertex = normalPerVertex;
 		ne_alias.Solid = solid;
 		ne_alias.Solid = solid;
+
+		ne_alias.CoordIndex.clear();
+		int counter = 0;
+		int32_t idx[3];
+		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+		{
+			idx[counter++] = *idx_it;
+			if (counter > 2)
+			{
+				counter = 0;
+				if(ccw)
+				{
+					ne_alias.CoordIndex.push_back(idx[0]);
+					ne_alias.CoordIndex.push_back(idx[1]);
+					ne_alias.CoordIndex.push_back(idx[2]);
+				}
+				else
+				{
+					ne_alias.CoordIndex.push_back(idx[0]);
+					ne_alias.CoordIndex.push_back(idx[2]);
+					ne_alias.CoordIndex.push_back(idx[1]);
+				}
+				ne_alias.CoordIndex.push_back(-1);
+			}
+		}// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
+
         // check for child nodes
         // check for child nodes
         if(!mReader->isEmptyElement())
         if(!mReader->isEmptyElement())
         {
         {
@@ -418,7 +480,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet()
     std::string use, def;
     std::string use, def;
     bool ccw = true;
     bool ccw = true;
     bool colorPerVertex = true;
     bool colorPerVertex = true;
-    std::list<int32_t> index;
+    std::vector<int32_t> index;
     bool normalPerVertex = true;
     bool normalPerVertex = true;
     bool solid = true;
     bool solid = true;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
@@ -427,7 +489,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet()
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
@@ -450,9 +512,42 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet()
 
 
 		ne_alias.CCW = ccw;
 		ne_alias.CCW = ccw;
 		ne_alias.ColorPerVertex = colorPerVertex;
 		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.CoordIndex = index;
 		ne_alias.NormalPerVertex = normalPerVertex;
 		ne_alias.NormalPerVertex = normalPerVertex;
 		ne_alias.Solid = solid;
 		ne_alias.Solid = solid;
+
+		ne_alias.CoordIndex.clear();
+		int counter = 0;
+		int32_t idx[3];
+		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+		{
+			idx[2] = *idx_it;
+			if (idx[2] < 0)
+			{
+				counter = 0;
+			}
+			else
+			{
+				if (counter >= 2)
+				{
+					if(ccw)
+					{
+						ne_alias.CoordIndex.push_back(idx[0]);
+						ne_alias.CoordIndex.push_back(idx[1]);
+						ne_alias.CoordIndex.push_back(idx[2]);
+					}
+					else
+					{
+						ne_alias.CoordIndex.push_back(idx[0]);
+						ne_alias.CoordIndex.push_back(idx[2]);
+						ne_alias.CoordIndex.push_back(idx[1]);
+					}
+					ne_alias.CoordIndex.push_back(-1);
+				}
+				idx[counter & 1] = idx[2];
+				++counter;
+			}
+		}// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
+
         // check for child nodes
         // check for child nodes
         if(!mReader->isEmptyElement())
         if(!mReader->isEmptyElement())
         {
         {
@@ -492,12 +587,12 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet()
 void X3DImporter::ParseNode_Rendering_LineSet()
 void X3DImporter::ParseNode_Rendering_LineSet()
 {
 {
     std::string use, def;
     std::string use, def;
-    std::list<int32_t> vertexCount;
+    std::vector<int32_t> vertexCount;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
 
 
 	MACRO_ATTRREAD_LOOPBEG;
 	MACRO_ATTRREAD_LOOPBEG;
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("vertexCount", vertexCount, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("vertexCount", vertexCount, XML_ReadNode_GetAttrVal_AsArrI32);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
 
 
 	// if "USE" defined then find already defined element.
 	// if "USE" defined then find already defined element.
@@ -521,7 +616,7 @@ void X3DImporter::ParseNode_Rendering_LineSet()
 		size_t coord_num = 0;
 		size_t coord_num = 0;
 
 
 		ne_alias.CoordIndex.clear();
 		ne_alias.CoordIndex.clear();
-		for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
 		{
 		{
 			if(*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
 			if(*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
 
 
@@ -627,7 +722,7 @@ void X3DImporter::ParseNode_Rendering_TriangleFanSet()
     std::string use, def;
     std::string use, def;
     bool ccw = true;
     bool ccw = true;
     bool colorPerVertex = true;
     bool colorPerVertex = true;
-    std::list<int32_t> fanCount;
+    std::vector<int32_t> fanCount;
     bool normalPerVertex = true;
     bool normalPerVertex = true;
     bool solid = true;
     bool solid = true;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
@@ -636,7 +731,7 @@ void X3DImporter::ParseNode_Rendering_TriangleFanSet()
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("fanCount", fanCount, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("fanCount", fanCount, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
@@ -669,7 +764,7 @@ void X3DImporter::ParseNode_Rendering_TriangleFanSet()
 		// assign indices for first triangle
 		// assign indices for first triangle
 		coord_num_first = 0;
 		coord_num_first = 0;
 		coord_num_prev = 1;
 		coord_num_prev = 1;
-		for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
 		{
 		{
 			if(*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
 			if(*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
 
 
@@ -818,7 +913,7 @@ void X3DImporter::ParseNode_Rendering_TriangleStripSet()
     std::string use, def;
     std::string use, def;
     bool ccw = true;
     bool ccw = true;
     bool colorPerVertex = true;
     bool colorPerVertex = true;
-    std::list<int32_t> stripCount;
+    std::vector<int32_t> stripCount;
     bool normalPerVertex = true;
     bool normalPerVertex = true;
     bool solid = true;
     bool solid = true;
     CX3DImporter_NodeElement* ne( nullptr );
     CX3DImporter_NodeElement* ne( nullptr );
@@ -827,7 +922,7 @@ void X3DImporter::ParseNode_Rendering_TriangleStripSet()
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("stripCount", stripCount, XML_ReadNode_GetAttrVal_AsListI32);
+		MACRO_ATTRREAD_CHECK_REF("stripCount", stripCount, XML_ReadNode_GetAttrVal_AsArrI32);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
 	MACRO_ATTRREAD_LOOPEND;
 	MACRO_ATTRREAD_LOOPEND;
@@ -860,7 +955,7 @@ void X3DImporter::ParseNode_Rendering_TriangleStripSet()
 
 
 		ne_alias.CoordIndex.clear();
 		ne_alias.CoordIndex.clear();
 		coord_num_sb = 0;
 		coord_num_sb = 0;
-		for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
 		{
 		{
 			if(*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
 			if(*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
 
 

+ 1675 - 0
code/X3DVocabulary.cpp

@@ -0,0 +1,1675 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/// \file   X3DVocabulary.cpp
+/// \brief  Vocabulary for Fast Infoset encoded binary X3D files.
+/// \date   2017
+/// \author Patrick Daehne
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "FIReader.hpp"
+
+namespace Assimp {
+
+static const char *encodingAlgorithmTable_3_2[] = {
+    "encoder://web3d.org/QuantizedFloatArrayEncoder",
+    "encoder://web3d.org/DeltazlibIntArrayEncoder",
+    "encoder://web3d.org/QuantizedzlibFloatArrayEncoder",
+    "encoder://web3d.org/zlibFloatArrayEncoder",
+    "encoder://web3d.org/QuantizedDoubleArrayEncoder",
+    "encoder://web3d.org/zlibDoubleArrayEncoder",
+    "encoder://web3d.org/QuantizedzlibDoubleArrayEncoder",
+    "encoder://web3d.org/RangeIntArrayEncoder"
+};
+
+static const std::shared_ptr<const FIValue> attributeValueTable_3_2[] = {
+    FIStringValue::create("false"),
+    FIStringValue::create("true")
+};
+
+static const FIQName elementNameTable_3_2[] = {
+    { "Shape", nullptr, nullptr },
+    { "Appearance", nullptr, nullptr },
+    { "Material", nullptr, nullptr },
+    { "IndexedFaceSet", nullptr, nullptr },
+    { "ProtoInstance", nullptr, nullptr },
+    { "Transform", nullptr, nullptr },
+    { "ImageTexture", nullptr, nullptr },
+    { "TextureTransform", nullptr, nullptr },
+    { "Coordinate", nullptr, nullptr },
+    { "Normal", nullptr, nullptr },
+    { "Color", nullptr, nullptr },
+    { "ColorRGBA", nullptr, nullptr },
+    { "TextureCoordinate", nullptr, nullptr },
+    { "ROUTE", nullptr, nullptr },
+    { "fieldValue", nullptr, nullptr },
+    { "Group", nullptr, nullptr },
+    { "LOD", nullptr, nullptr },
+    { "Switch", nullptr, nullptr },
+    { "Script", nullptr, nullptr },
+    { "IndexedTriangleFanSet", nullptr, nullptr },
+    { "IndexedTriangleSet", nullptr, nullptr },
+    { "IndexedTriangleStripSet", nullptr, nullptr },
+    { "MultiTexture", nullptr, nullptr },
+    { "MultiTextureCoordinate", nullptr, nullptr },
+    { "MultiTextureTransform", nullptr, nullptr },
+    { "IndexedLineSet", nullptr, nullptr },
+    { "PointSet", nullptr, nullptr },
+    { "StaticGroup", nullptr, nullptr },
+    { "Sphere", nullptr, nullptr },
+    { "Box", nullptr, nullptr },
+    { "Cone", nullptr, nullptr },
+    { "Anchor", nullptr, nullptr },
+    { "Arc2D", nullptr, nullptr },
+    { "ArcClose2D", nullptr, nullptr },
+    { "AudioClip", nullptr, nullptr },
+    { "Background", nullptr, nullptr },
+    { "Billboard", nullptr, nullptr },
+    { "BooleanFilter", nullptr, nullptr },
+    { "BooleanSequencer", nullptr, nullptr },
+    { "BooleanToggle", nullptr, nullptr },
+    { "BooleanTrigger", nullptr, nullptr },
+    { "Circle2D", nullptr, nullptr },
+    { "Collision", nullptr, nullptr },
+    { "ColorInterpolator", nullptr, nullptr },
+    { "Contour2D", nullptr, nullptr },
+    { "ContourPolyline2D", nullptr, nullptr },
+    { "CoordinateDouble", nullptr, nullptr },
+    { "CoordinateInterpolator", nullptr, nullptr },
+    { "CoordinateInterpolator2D", nullptr, nullptr },
+    { "Cylinder", nullptr, nullptr },
+    { "CylinderSensor", nullptr, nullptr },
+    { "DirectionalLight", nullptr, nullptr },
+    { "Disk2D", nullptr, nullptr },
+    { "EXPORT", nullptr, nullptr },
+    { "ElevationGrid", nullptr, nullptr },
+    { "EspduTransform", nullptr, nullptr },
+    { "ExternProtoDeclare", nullptr, nullptr },
+    { "Extrusion", nullptr, nullptr },
+    { "FillProperties", nullptr, nullptr },
+    { "Fog", nullptr, nullptr },
+    { "FontStyle", nullptr, nullptr },
+    { "GeoCoordinate", nullptr, nullptr },
+    { "GeoElevationGrid", nullptr, nullptr },
+    { "GeoLOD", nullptr, nullptr },
+    { "GeoLocation", nullptr, nullptr },
+    { "GeoMetadata", nullptr, nullptr },
+    { "GeoOrigin", nullptr, nullptr },
+    { "GeoPositionInterpolator", nullptr, nullptr },
+    { "GeoTouchSensor", nullptr, nullptr },
+    { "GeoViewpoint", nullptr, nullptr },
+    { "HAnimDisplacer", nullptr, nullptr },
+    { "HAnimHumanoid", nullptr, nullptr },
+    { "HAnimJoint", nullptr, nullptr },
+    { "HAnimSegment", nullptr, nullptr },
+    { "HAnimSite", nullptr, nullptr },
+    { "IMPORT", nullptr, nullptr },
+    { "IS", nullptr, nullptr },
+    { "Inline", nullptr, nullptr },
+    { "IntegerSequencer", nullptr, nullptr },
+    { "IntegerTrigger", nullptr, nullptr },
+    { "KeySensor", nullptr, nullptr },
+    { "LineProperties", nullptr, nullptr },
+    { "LineSet", nullptr, nullptr },
+    { "LoadSensor", nullptr, nullptr },
+    { "MetadataDouble", nullptr, nullptr },
+    { "MetadataFloat", nullptr, nullptr },
+    { "MetadataInteger", nullptr, nullptr },
+    { "MetadataSet", nullptr, nullptr },
+    { "MetadataString", nullptr, nullptr },
+    { "MovieTexture", nullptr, nullptr },
+    { "NavigationInfo", nullptr, nullptr },
+    { "NormalInterpolator", nullptr, nullptr },
+    { "NurbsCurve", nullptr, nullptr },
+    { "NurbsCurve2D", nullptr, nullptr },
+    { "NurbsOrientationInterpolator", nullptr, nullptr },
+    { "NurbsPatchSurface", nullptr, nullptr },
+    { "NurbsPositionInterpolator", nullptr, nullptr },
+    { "NurbsSet", nullptr, nullptr },
+    { "NurbsSurfaceInterpolator", nullptr, nullptr },
+    { "NurbsSweptSurface", nullptr, nullptr },
+    { "NurbsSwungSurface", nullptr, nullptr },
+    { "NurbsTextureCoordinate", nullptr, nullptr },
+    { "NurbsTrimmedSurface", nullptr, nullptr },
+    { "OrientationInterpolator", nullptr, nullptr },
+    { "PixelTexture", nullptr, nullptr },
+    { "PlaneSensor", nullptr, nullptr },
+    { "PointLight", nullptr, nullptr },
+    { "Polyline2D", nullptr, nullptr },
+    { "Polypoint2D", nullptr, nullptr },
+    { "PositionInterpolator", nullptr, nullptr },
+    { "PositionInterpolator2D", nullptr, nullptr },
+    { "ProtoBody", nullptr, nullptr },
+    { "ProtoDeclare", nullptr, nullptr },
+    { "ProtoInterface", nullptr, nullptr },
+    { "ProximitySensor", nullptr, nullptr },
+    { "ReceiverPdu", nullptr, nullptr },
+    { "Rectangle2D", nullptr, nullptr },
+    { "ScalarInterpolator", nullptr, nullptr },
+    { "Scene", nullptr, nullptr },
+    { "SignalPdu", nullptr, nullptr },
+    { "Sound", nullptr, nullptr },
+    { "SphereSensor", nullptr, nullptr },
+    { "SpotLight", nullptr, nullptr },
+    { "StringSensor", nullptr, nullptr },
+    { "Text", nullptr, nullptr },
+    { "TextureBackground", nullptr, nullptr },
+    { "TextureCoordinateGenerator", nullptr, nullptr },
+    { "TimeSensor", nullptr, nullptr },
+    { "TimeTrigger", nullptr, nullptr },
+    { "TouchSensor", nullptr, nullptr },
+    { "TransmitterPdu", nullptr, nullptr },
+    { "TriangleFanSet", nullptr, nullptr },
+    { "TriangleSet", nullptr, nullptr },
+    { "TriangleSet2D", nullptr, nullptr },
+    { "TriangleStripSet", nullptr, nullptr },
+    { "Viewpoint", nullptr, nullptr },
+    { "VisibilitySensor", nullptr, nullptr },
+    { "WorldInfo", nullptr, nullptr },
+    { "X3D", nullptr, nullptr },
+    { "component", nullptr, nullptr },
+    { "connect", nullptr, nullptr },
+    { "field", nullptr, nullptr },
+    { "head", nullptr, nullptr },
+    { "humanoidBodyType", nullptr, nullptr },
+    { "meta", nullptr, nullptr },
+    { "CADAssembly", nullptr, nullptr },
+    { "CADFace", nullptr, nullptr },
+    { "CADLayer", nullptr, nullptr },
+    { "CADPart", nullptr, nullptr },
+    { "ComposedCubeMapTexture", nullptr, nullptr },
+    { "ComposedShader", nullptr, nullptr },
+    { "ComposedTexture3D", nullptr, nullptr },
+    { "FloatVertexAttribute", nullptr, nullptr },
+    { "FogCoordinate", nullptr, nullptr },
+    { "GeneratedCubeMapTexture", nullptr, nullptr },
+    { "ImageCubeMapTexture", nullptr, nullptr },
+    { "ImageTexture3D", nullptr, nullptr },
+    { "IndexedQuadSet", nullptr, nullptr },
+    { "LocalFog", nullptr, nullptr },
+    { "Matrix3VertexAttribute", nullptr, nullptr },
+    { "Matrix4VertexAttribute", nullptr, nullptr },
+    { "PackagedShader", nullptr, nullptr },
+    { "PixelTexture3D", nullptr, nullptr },
+    { "ProgramShader", nullptr, nullptr },
+    { "QuadSet", nullptr, nullptr },
+    { "ShaderPart", nullptr, nullptr },
+    { "ShaderProgram", nullptr, nullptr },
+    { "TextureCoordinate3D", nullptr, nullptr },
+    { "TextureCoordinate4D", nullptr, nullptr },
+    { "TextureTransform3D", nullptr, nullptr },
+    { "TextureTransformMatrix3D", nullptr, nullptr },
+    { "BallJoint", nullptr, nullptr },
+    { "BoundedPhysicsModel", nullptr, nullptr },
+    { "ClipPlane", nullptr, nullptr },
+    { "CollidableOffset", nullptr, nullptr },
+    { "CollidableShape", nullptr, nullptr },
+    { "CollisionCollection", nullptr, nullptr },
+    { "CollisionSensor", nullptr, nullptr },
+    { "CollisionSpace", nullptr, nullptr },
+    { "ColorDamper", nullptr, nullptr },
+    { "ConeEmitter", nullptr, nullptr },
+    { "Contact", nullptr, nullptr },
+    { "CoordinateDamper", nullptr, nullptr },
+    { "DISEntityManager", nullptr, nullptr },
+    { "DISEntityTypeMapping", nullptr, nullptr },
+    { "DoubleAxisHingeJoint", nullptr, nullptr },
+    { "EaseInEaseOut", nullptr, nullptr },
+    { "ExplosionEmitter", nullptr, nullptr },
+    { "ForcePhysicsModel", nullptr, nullptr },
+    { "GeoProximitySensor", nullptr, nullptr },
+    { "GeoTransform", nullptr, nullptr },
+    { "Layer", nullptr, nullptr },
+    { "LayerSet", nullptr, nullptr },
+    { "Layout", nullptr, nullptr },
+    { "LayoutGroup", nullptr, nullptr },
+    { "LayoutLayer", nullptr, nullptr },
+    { "LinePickSensor", nullptr, nullptr },
+    { "MotorJoint", nullptr, nullptr },
+    { "OrientationChaser", nullptr, nullptr },
+    { "OrientationDamper", nullptr, nullptr },
+    { "OrthoViewpoint", nullptr, nullptr },
+    { "ParticleSystem", nullptr, nullptr },
+    { "PickableGroup", nullptr, nullptr },
+    { "PointEmitter", nullptr, nullptr },
+    { "PointPickSensor", nullptr, nullptr },
+    { "PolylineEmitter", nullptr, nullptr },
+    { "PositionChaser", nullptr, nullptr },
+    { "PositionChaser2D", nullptr, nullptr },
+    { "PositionDamper", nullptr, nullptr },
+    { "PositionDamper2D", nullptr, nullptr },
+    { "PrimitivePickSensor", nullptr, nullptr },
+    { "RigidBody", nullptr, nullptr },
+    { "RigidBodyCollection", nullptr, nullptr },
+    { "ScalarChaser", nullptr, nullptr },
+    { "ScreenFontStyle", nullptr, nullptr },
+    { "ScreenGroup", nullptr, nullptr },
+    { "SingleAxisHingeJoint", nullptr, nullptr },
+    { "SliderJoint", nullptr, nullptr },
+    { "SplinePositionInterpolator", nullptr, nullptr },
+    { "SplinePositionInterpolator2D", nullptr, nullptr },
+    { "SplineScalarInterpolator", nullptr, nullptr },
+    { "SquadOrientationInterpolator", nullptr, nullptr },
+    { "SurfaceEmitter", nullptr, nullptr },
+    { "TexCoordDamper", nullptr, nullptr },
+    { "TextureProperties", nullptr, nullptr },
+    { "TransformSensor", nullptr, nullptr },
+    { "TwoSidedMaterial", nullptr, nullptr },
+    { "UniversalJoint", nullptr, nullptr },
+    { "ViewpointGroup", nullptr, nullptr },
+    { "Viewport", nullptr, nullptr },
+    { "VolumeEmitter", nullptr, nullptr },
+    { "VolumePickSensor", nullptr, nullptr },
+    { "WindPhysicsModel", nullptr, nullptr }
+};
+
+static const FIQName attributeNameTable_3_2[] = {
+    { "DEF", nullptr, nullptr },
+    { "USE", nullptr, nullptr },
+    { "containerField", nullptr, nullptr },
+    { "fromNode", nullptr, nullptr },
+    { "fromField", nullptr, nullptr },
+    { "toNode", nullptr, nullptr },
+    { "toField", nullptr, nullptr },
+    { "name", nullptr, nullptr },
+    { "value", nullptr, nullptr },
+    { "color", nullptr, nullptr },
+    { "colorIndex", nullptr, nullptr },
+    { "coordIndex", nullptr, nullptr },
+    { "texCoordIndex", nullptr, nullptr },
+    { "normalIndex", nullptr, nullptr },
+    { "colorPerVertex", nullptr, nullptr },
+    { "normalPerVertex", nullptr, nullptr },
+    { "rotation", nullptr, nullptr },
+    { "scale", nullptr, nullptr },
+    { "center", nullptr, nullptr },
+    { "scaleOrientation", nullptr, nullptr },
+    { "translation", nullptr, nullptr },
+    { "url", nullptr, nullptr },
+    { "repeatS", nullptr, nullptr },
+    { "repeatT", nullptr, nullptr },
+    { "point", nullptr, nullptr },
+    { "vector", nullptr, nullptr },
+    { "range", nullptr, nullptr },
+    { "ambientIntensity", nullptr, nullptr },
+    { "diffuseColor", nullptr, nullptr },
+    { "emissiveColor", nullptr, nullptr },
+    { "shininess", nullptr, nullptr },
+    { "specularColor", nullptr, nullptr },
+    { "transparency", nullptr, nullptr },
+    { "whichChoice", nullptr, nullptr },
+    { "index", nullptr, nullptr },
+    { "mode", nullptr, nullptr },
+    { "source", nullptr, nullptr },
+    { "function", nullptr, nullptr },
+    { "alpha", nullptr, nullptr },
+    { "vertexCount", nullptr, nullptr },
+    { "radius", nullptr, nullptr },
+    { "size", nullptr, nullptr },
+    { "height", nullptr, nullptr },
+    { "solid", nullptr, nullptr },
+    { "ccw", nullptr, nullptr },
+    { "key", nullptr, nullptr },
+    { "keyValue", nullptr, nullptr },
+    { "enabled", nullptr, nullptr },
+    { "direction", nullptr, nullptr },
+    { "position", nullptr, nullptr },
+    { "orientation", nullptr, nullptr },
+    { "bboxCenter", nullptr, nullptr },
+    { "bboxSize", nullptr, nullptr },
+    { "AS", nullptr, nullptr },
+    { "InlineDEF", nullptr, nullptr },
+    { "accessType", nullptr, nullptr },
+    { "actionKeyPress", nullptr, nullptr },
+    { "actionKeyRelease", nullptr, nullptr },
+    { "address", nullptr, nullptr },
+    { "altKey", nullptr, nullptr },
+    { "antennaLocation", nullptr, nullptr },
+    { "antennaPatternLength", nullptr, nullptr },
+    { "antennaPatternType", nullptr, nullptr },
+    { "applicationID", nullptr, nullptr },
+    { "articulationParameterArray", nullptr, nullptr },
+    { "articulationParameterChangeIndicatorArray", nullptr, nullptr },
+    { "articulationParameterCount", nullptr, nullptr },
+    { "articulationParameterDesignatorArray", nullptr, nullptr },
+    { "articulationParameterIdPartAttachedArray", nullptr, nullptr },
+    { "articulationParameterTypeArray", nullptr, nullptr },
+    { "attenuation", nullptr, nullptr },
+    { "autoOffset", nullptr, nullptr },
+    { "avatarSize", nullptr, nullptr },
+    { "axisOfRotation", nullptr, nullptr },
+    { "backUrl", nullptr, nullptr },
+    { "beamWidth", nullptr, nullptr },
+    { "beginCap", nullptr, nullptr },
+    { "bindTime", nullptr, nullptr },
+    { "bottom", nullptr, nullptr },
+    { "bottomRadius", nullptr, nullptr },
+    { "bottomUrl", nullptr, nullptr },
+    { "centerOfMass", nullptr, nullptr },
+    { "centerOfRotation", nullptr, nullptr },
+    { "child1Url", nullptr, nullptr },
+    { "child2Url", nullptr, nullptr },
+    { "child3Url", nullptr, nullptr },
+    { "child4Url", nullptr, nullptr },
+    { "class", nullptr, nullptr },
+    { "closureType", nullptr, nullptr },
+    { "collideTime", nullptr, nullptr },
+    { "content", nullptr, nullptr },
+    { "controlKey", nullptr, nullptr },
+    { "controlPoint", nullptr, nullptr },
+    { "convex", nullptr, nullptr },
+    { "coordinateSystem", nullptr, nullptr },
+    { "copyright", nullptr, nullptr },
+    { "creaseAngle", nullptr, nullptr },
+    { "crossSection", nullptr, nullptr },
+    { "cryptoKeyID", nullptr, nullptr },
+    { "cryptoSystem", nullptr, nullptr },
+    { "cutOffAngle", nullptr, nullptr },
+    { "cycleInterval", nullptr, nullptr },
+    { "cycleTime", nullptr, nullptr },
+    { "data", nullptr, nullptr },
+    { "dataFormat", nullptr, nullptr },
+    { "dataLength", nullptr, nullptr },
+    { "dataUrl", nullptr, nullptr },
+    { "date", nullptr, nullptr },
+    { "deadReckoning", nullptr, nullptr },
+    { "deletionAllowed", nullptr, nullptr },
+    { "description", nullptr, nullptr },
+    { "detonateTime", nullptr, nullptr },
+    { "dir", nullptr, nullptr },
+    { "directOutput", nullptr, nullptr },
+    { "diskAngle", nullptr, nullptr },
+    { "displacements", nullptr, nullptr },
+    { "documentation", nullptr, nullptr },
+    { "elapsedTime", nullptr, nullptr },
+    { "ellipsoid", nullptr, nullptr },
+    { "encodingScheme", nullptr, nullptr },
+    { "endAngle", nullptr, nullptr },
+    { "endCap", nullptr, nullptr },
+    { "enterTime", nullptr, nullptr },
+    { "enteredText", nullptr, nullptr },
+    { "entityCategory", nullptr, nullptr },
+    { "entityCountry", nullptr, nullptr },
+    { "entityDomain", nullptr, nullptr },
+    { "entityExtra", nullptr, nullptr },
+    { "entityID", nullptr, nullptr },
+    { "entityKind", nullptr, nullptr },
+    { "entitySpecific", nullptr, nullptr },
+    { "entitySubCategory", nullptr, nullptr },
+    { "exitTime", nullptr, nullptr },
+    { "extent", nullptr, nullptr },
+    { "family", nullptr, nullptr },
+    { "fanCount", nullptr, nullptr },
+    { "fieldOfView", nullptr, nullptr },
+    { "filled", nullptr, nullptr },
+    { "finalText", nullptr, nullptr },
+    { "fireMissionIndex", nullptr, nullptr },
+    { "fired1", nullptr, nullptr },
+    { "fired2", nullptr, nullptr },
+    { "firedTime", nullptr, nullptr },
+    { "firingRange", nullptr, nullptr },
+    { "firingRate", nullptr, nullptr },
+    { "fogType", nullptr, nullptr },
+    { "forceID", nullptr, nullptr },
+    { "frequency", nullptr, nullptr },
+    { "frontUrl", nullptr, nullptr },
+    { "fuse", nullptr, nullptr },
+    { "geoCoords", nullptr, nullptr },
+    { "geoGridOrigin", nullptr, nullptr },
+    { "geoSystem", nullptr, nullptr },
+    { "groundAngle", nullptr, nullptr },
+    { "groundColor", nullptr, nullptr },
+    { "hatchColor", nullptr, nullptr },
+    { "hatchStyle", nullptr, nullptr },
+    { "hatched", nullptr, nullptr },
+    { "headlight", nullptr, nullptr },
+    { "horizontal", nullptr, nullptr },
+    { "horizontalDatum", nullptr, nullptr },
+    { "http-equiv", nullptr, nullptr },
+    { "image", nullptr, nullptr },
+    { "importedDEF", nullptr, nullptr },
+    { "info", nullptr, nullptr },
+    { "innerRadius", nullptr, nullptr },
+    { "inputFalse", nullptr, nullptr },
+    { "inputNegate", nullptr, nullptr },
+    { "inputSource", nullptr, nullptr },
+    { "inputTrue", nullptr, nullptr },
+    { "integerKey", nullptr, nullptr },
+    { "intensity", nullptr, nullptr },
+    { "jump", nullptr, nullptr },
+    { "justify", nullptr, nullptr },
+    { "keyPress", nullptr, nullptr },
+    { "keyRelease", nullptr, nullptr },
+    { "knot", nullptr, nullptr },
+    { "lang", nullptr, nullptr },
+    { "language", nullptr, nullptr },
+    { "leftToRight", nullptr, nullptr },
+    { "leftUrl", nullptr, nullptr },
+    { "length", nullptr, nullptr },
+    { "lengthOfModulationParameters", nullptr, nullptr },
+    { "level", nullptr, nullptr },
+    { "limitOrientation", nullptr, nullptr },
+    { "lineSegments", nullptr, nullptr },
+    { "linearAcceleration", nullptr, nullptr },
+    { "linearVelocity", nullptr, nullptr },
+    { "linetype", nullptr, nullptr },
+    { "linewidthScaleFactor", nullptr, nullptr },
+    { "llimit", nullptr, nullptr },
+    { "load", nullptr, nullptr },
+    { "loadTime", nullptr, nullptr },
+    { "localDEF", nullptr, nullptr },
+    { "location", nullptr, nullptr },
+    { "loop", nullptr, nullptr },
+    { "marking", nullptr, nullptr },
+    { "mass", nullptr, nullptr },
+    { "maxAngle", nullptr, nullptr },
+    { "maxBack", nullptr, nullptr },
+    { "maxExtent", nullptr, nullptr },
+    { "maxFront", nullptr, nullptr },
+    { "maxPosition", nullptr, nullptr },
+    { "metadataFormat", nullptr, nullptr },
+    { "minAngle", nullptr, nullptr },
+    { "minBack", nullptr, nullptr },
+    { "minFront", nullptr, nullptr },
+    { "minPosition", nullptr, nullptr },
+    { "modulationTypeDetail", nullptr, nullptr },
+    { "modulationTypeMajor", nullptr, nullptr },
+    { "modulationTypeSpreadSpectrum", nullptr, nullptr },
+    { "modulationTypeSystem", nullptr, nullptr },
+    { "momentsOfInertia", nullptr, nullptr },
+    { "multicastRelayHost", nullptr, nullptr },
+    { "multicastRelayPort", nullptr, nullptr },
+    { "munitionApplicationID", nullptr, nullptr },
+    { "munitionEndPoint", nullptr, nullptr },
+    { "munitionEntityID", nullptr, nullptr },
+    { "munitionQuantity", nullptr, nullptr },
+    { "munitionSiteID", nullptr, nullptr },
+    { "munitionStartPoint", nullptr, nullptr },
+    { "mustEvaluate", nullptr, nullptr },
+    { "navType", nullptr, nullptr },
+    { "networkMode", nullptr, nullptr },
+    { "next", nullptr, nullptr },
+    { "nodeField", nullptr, nullptr },
+    { "offset", nullptr, nullptr },
+    { "on", nullptr, nullptr },
+    { "order", nullptr, nullptr },
+    { "originator", nullptr, nullptr },
+    { "outerRadius", nullptr, nullptr },
+    { "parameter", nullptr, nullptr },
+    { "pauseTime", nullptr, nullptr },
+    { "pitch", nullptr, nullptr },
+    { "points", nullptr, nullptr },
+    { "port", nullptr, nullptr },
+    { "power", nullptr, nullptr },
+    { "previous", nullptr, nullptr },
+    { "priority", nullptr, nullptr },
+    { "profile", nullptr, nullptr },
+    { "progress", nullptr, nullptr },
+    { "protoField", nullptr, nullptr },
+    { "radioEntityTypeCategory", nullptr, nullptr },
+    { "radioEntityTypeCountry", nullptr, nullptr },
+    { "radioEntityTypeDomain", nullptr, nullptr },
+    { "radioEntityTypeKind", nullptr, nullptr },
+    { "radioEntityTypeNomenclature", nullptr, nullptr },
+    { "radioEntityTypeNomenclatureVersion", nullptr, nullptr },
+    { "radioID", nullptr, nullptr },
+    { "readInterval", nullptr, nullptr },
+    { "receivedPower", nullptr, nullptr },
+    { "receiverState", nullptr, nullptr },
+    { "reference", nullptr, nullptr },
+    { "relativeAntennaLocation", nullptr, nullptr },
+    { "resolution", nullptr, nullptr },
+    { "resumeTime", nullptr, nullptr },
+    { "rightUrl", nullptr, nullptr },
+    { "rootUrl", nullptr, nullptr },
+    { "rotateYUp", nullptr, nullptr },
+    { "rtpHeaderExpected", nullptr, nullptr },
+    { "sampleRate", nullptr, nullptr },
+    { "samples", nullptr, nullptr },
+    { "shiftKey", nullptr, nullptr },
+    { "side", nullptr, nullptr },
+    { "siteID", nullptr, nullptr },
+    { "skinCoordIndex", nullptr, nullptr },
+    { "skinCoordWeight", nullptr, nullptr },
+    { "skyAngle", nullptr, nullptr },
+    { "skyColor", nullptr, nullptr },
+    { "spacing", nullptr, nullptr },
+    { "spatialize", nullptr, nullptr },
+    { "speed", nullptr, nullptr },
+    { "speedFactor", nullptr, nullptr },
+    { "spine", nullptr, nullptr },
+    { "startAngle", nullptr, nullptr },
+    { "startTime", nullptr, nullptr },
+    { "stiffness", nullptr, nullptr },
+    { "stopTime", nullptr, nullptr },
+    { "string", nullptr, nullptr },
+    { "stripCount", nullptr, nullptr },
+    { "style", nullptr, nullptr },
+    { "summary", nullptr, nullptr },
+    { "tdlType", nullptr, nullptr },
+    { "tessellation", nullptr, nullptr },
+    { "tessellationScale", nullptr, nullptr },
+    { "time", nullptr, nullptr },
+    { "timeOut", nullptr, nullptr },
+    { "timestamp", nullptr, nullptr },
+    { "title", nullptr, nullptr },
+    { "toggle", nullptr, nullptr },
+    { "top", nullptr, nullptr },
+    { "topToBottom", nullptr, nullptr },
+    { "topUrl", nullptr, nullptr },
+    { "touchTime", nullptr, nullptr },
+    { "transmitFrequencyBandwidth", nullptr, nullptr },
+    { "transmitState", nullptr, nullptr },
+    { "transmitterApplicationID", nullptr, nullptr },
+    { "transmitterEntityID", nullptr, nullptr },
+    { "transmitterRadioID", nullptr, nullptr },
+    { "transmitterSiteID", nullptr, nullptr },
+    { "transparent", nullptr, nullptr },
+    { "triggerTime", nullptr, nullptr },
+    { "triggerTrue", nullptr, nullptr },
+    { "triggerValue", nullptr, nullptr },
+    { "type", nullptr, nullptr },
+    { "uDimension", nullptr, nullptr },
+    { "uKnot", nullptr, nullptr },
+    { "uOrder", nullptr, nullptr },
+    { "uTessellation", nullptr, nullptr },
+    { "ulimit", nullptr, nullptr },
+    { "vDimension", nullptr, nullptr },
+    { "vKnot", nullptr, nullptr },
+    { "vOrder", nullptr, nullptr },
+    { "vTessellation", nullptr, nullptr },
+    { "version", nullptr, nullptr },
+    { "verticalDatum", nullptr, nullptr },
+    { "vertices", nullptr, nullptr },
+    { "visibilityLimit", nullptr, nullptr },
+    { "visibilityRange", nullptr, nullptr },
+    { "warhead", nullptr, nullptr },
+    { "weight", nullptr, nullptr },
+    { "whichGeometry", nullptr, nullptr },
+    { "writeInterval", nullptr, nullptr },
+    { "xDimension", nullptr, nullptr },
+    { "xSpacing", nullptr, nullptr },
+    { "yScale", nullptr, nullptr },
+    { "zDimension", nullptr, nullptr },
+    { "zSpacing", nullptr, nullptr },
+    { "visible", nullptr, nullptr },
+    { "repeatR", nullptr, nullptr },
+    { "texture", nullptr, nullptr },
+    { "back", nullptr, nullptr },
+    { "front", nullptr, nullptr },
+    { "left", nullptr, nullptr },
+    { "right", nullptr, nullptr },
+    { "parts", nullptr, nullptr },
+    { "isSelected", nullptr, nullptr },
+    { "isValid", nullptr, nullptr },
+    { "numComponents", nullptr, nullptr },
+    { "depth", nullptr, nullptr },
+    { "update", nullptr, nullptr },
+    { "fogCoord", nullptr, nullptr },
+    { "texCoord", nullptr, nullptr },
+    { "activate", nullptr, nullptr },
+    { "programs", nullptr, nullptr },
+    { "matrix", nullptr, nullptr },
+    { "anchorPoint", nullptr, nullptr },
+    { "body1", nullptr, nullptr },
+    { "body2", nullptr, nullptr },
+    { "mustOutput", nullptr, nullptr },
+    { "body1AnchorPoint", nullptr, nullptr },
+    { "body2AnchorPoint", nullptr, nullptr },
+    { "plane", nullptr, nullptr },
+    { "appliedParameters", nullptr, nullptr },
+    { "bounce", nullptr, nullptr },
+    { "frictionCoefficients", nullptr, nullptr },
+    { "minBounceSpeed", nullptr, nullptr },
+    { "slipFactors", nullptr, nullptr },
+    { "softnessConstantForceMix", nullptr, nullptr },
+    { "softnessErrorCorrection", nullptr, nullptr },
+    { "surfaceSpeed", nullptr, nullptr },
+    { "isActive", nullptr, nullptr },
+    { "useGeometry", nullptr, nullptr },
+    { "set_destination", nullptr, nullptr },
+    { "set_value", nullptr, nullptr },
+    { "tau", nullptr, nullptr },
+    { "tolerance", nullptr, nullptr },
+    { "value_changed", nullptr, nullptr },
+    { "initialDestination", nullptr, nullptr },
+    { "initialValue", nullptr, nullptr },
+    { "angle", nullptr, nullptr },
+    { "variation", nullptr, nullptr },
+    { "surfaceArea", nullptr, nullptr },
+    { "frictionDirection", nullptr, nullptr },
+    { "slipCoefficients", nullptr, nullptr },
+    { "category", nullptr, nullptr },
+    { "country", nullptr, nullptr },
+    { "domain", nullptr, nullptr },
+    { "extra", nullptr, nullptr },
+    { "kind", nullptr, nullptr },
+    { "specific", nullptr, nullptr },
+    { "subcategory", nullptr, nullptr },
+    { "axis1", nullptr, nullptr },
+    { "axis2", nullptr, nullptr },
+    { "desiredAngularVelocity1", nullptr, nullptr },
+    { "desiredAngularVelocity2", nullptr, nullptr },
+    { "maxAngle1", nullptr, nullptr },
+    { "maxTorque1", nullptr, nullptr },
+    { "maxTorque2", nullptr, nullptr },
+    { "minAngle1", nullptr, nullptr },
+    { "stopBounce1", nullptr, nullptr },
+    { "stopConstantForceMix1", nullptr, nullptr },
+    { "stopErrorCorrection1", nullptr, nullptr },
+    { "suspensionErrorCorrection", nullptr, nullptr },
+    { "suspensionForce", nullptr, nullptr },
+    { "body1Axis", nullptr, nullptr },
+    { "body2Axis", nullptr, nullptr },
+    { "hinge1Angle", nullptr, nullptr },
+    { "hinge1AngleRate", nullptr, nullptr },
+    { "hinge2Angle", nullptr, nullptr },
+    { "hinge2AngleRate", nullptr, nullptr },
+    { "set_fraction", nullptr, nullptr },
+    { "easeInEaseOut", nullptr, nullptr },
+    { "modifiedFraction_changed", nullptr, nullptr },
+    { "force", nullptr, nullptr },
+    { "geoCenter", nullptr, nullptr },
+    { "centerOfRotation_changed", nullptr, nullptr },
+    { "geoCoord_changed", nullptr, nullptr },
+    { "orientation_changed", nullptr, nullptr },
+    { "position_changed", nullptr, nullptr },
+    { "isPickable", nullptr, nullptr },
+    { "viewport", nullptr, nullptr },
+    { "activeLayer", nullptr, nullptr },
+    { "align", nullptr, nullptr },
+    { "offsetUnits", nullptr, nullptr },
+    { "scaleMode", nullptr, nullptr },
+    { "sizeUnits", nullptr, nullptr },
+    { "layout", nullptr, nullptr },
+    { "objectType", nullptr, nullptr },
+    { "pickedNormal", nullptr, nullptr },
+    { "pickedPoint", nullptr, nullptr },
+    { "pickedTextureCoordinate", nullptr, nullptr },
+    { "intersectionType", nullptr, nullptr },
+    { "sortOrder", nullptr, nullptr },
+    { "axis1Angle", nullptr, nullptr },
+    { "axis1Torque", nullptr, nullptr },
+    { "axis2Angle", nullptr, nullptr },
+    { "axis2Torque", nullptr, nullptr },
+    { "axis3Angle", nullptr, nullptr },
+    { "axis3Torque", nullptr, nullptr },
+    { "enabledAxies", nullptr, nullptr },
+    { "motor1Axis", nullptr, nullptr },
+    { "motor2Axis", nullptr, nullptr },
+    { "motor3Axis", nullptr, nullptr },
+    { "stop1Bounce", nullptr, nullptr },
+    { "stop1ErrorCorrection", nullptr, nullptr },
+    { "stop2Bounce", nullptr, nullptr },
+    { "stop2ErrorCorrection", nullptr, nullptr },
+    { "stop3Bounce", nullptr, nullptr },
+    { "stop3ErrorCorrection", nullptr, nullptr },
+    { "motor1Angle", nullptr, nullptr },
+    { "motor1AngleRate", nullptr, nullptr },
+    { "motor2Angle", nullptr, nullptr },
+    { "motor2AngleRate", nullptr, nullptr },
+    { "motor3Angle", nullptr, nullptr },
+    { "motor3AngleRate", nullptr, nullptr },
+    { "autoCalc", nullptr, nullptr },
+    { "duration", nullptr, nullptr },
+    { "retainUserOffsets", nullptr, nullptr },
+    { "isBound", nullptr, nullptr },
+    { "appearance", nullptr, nullptr },
+    { "createParticles", nullptr, nullptr },
+    { "lifetimeVariation", nullptr, nullptr },
+    { "maxParticles", nullptr, nullptr },
+    { "particleLifetime", nullptr, nullptr },
+    { "particleSize", nullptr, nullptr },
+    { "colorKey", nullptr, nullptr },
+    { "geometryType", nullptr, nullptr },
+    { "texCoordKey", nullptr, nullptr },
+    { "pickable", nullptr, nullptr },
+    { "angularDampingFactor", nullptr, nullptr },
+    { "angularVelocity", nullptr, nullptr },
+    { "autoDamp", nullptr, nullptr },
+    { "autoDisable", nullptr, nullptr },
+    { "disableAngularSpeed", nullptr, nullptr },
+    { "disableLinearSpeed", nullptr, nullptr },
+    { "disableTime", nullptr, nullptr },
+    { "finiteRotationAxis", nullptr, nullptr },
+    { "fixed", nullptr, nullptr },
+    { "forces", nullptr, nullptr },
+    { "inertia", nullptr, nullptr },
+    { "linearDampingFactor", nullptr, nullptr },
+    { "torques", nullptr, nullptr },
+    { "useFiniteRotation", nullptr, nullptr },
+    { "useGlobalForce", nullptr, nullptr },
+    { "constantForceMix", nullptr, nullptr },
+    { "constantSurfaceThickness", nullptr, nullptr },
+    { "errorCorrection", nullptr, nullptr },
+    { "iterations", nullptr, nullptr },
+    { "maxCorrectionSpeed", nullptr, nullptr },
+    { "preferAccuracy", nullptr, nullptr },
+    { "pointSize", nullptr, nullptr },
+    { "stopBounce", nullptr, nullptr },
+    { "stopErrorCorrection", nullptr, nullptr },
+    { "angleRate", nullptr, nullptr },
+    { "maxSeparation", nullptr, nullptr },
+    { "minSeparation", nullptr, nullptr },
+    { "separation", nullptr, nullptr },
+    { "separationRate", nullptr, nullptr },
+    { "closed", nullptr, nullptr },
+    { "keyVelocity", nullptr, nullptr },
+    { "normalizeVelocity", nullptr, nullptr },
+    { "surface", nullptr, nullptr },
+    { "anisotropicDegree", nullptr, nullptr },
+    { "borderColor", nullptr, nullptr },
+    { "borderWidth", nullptr, nullptr },
+    { "boundaryModeS", nullptr, nullptr },
+    { "boundaryModeT", nullptr, nullptr },
+    { "boundaryModeR", nullptr, nullptr },
+    { "magnificationFilter", nullptr, nullptr },
+    { "minificationFilter", nullptr, nullptr },
+    { "textureCompression", nullptr, nullptr },
+    { "texturePriority", nullptr, nullptr },
+    { "generateMipMaps", nullptr, nullptr },
+    { "targetObject", nullptr, nullptr },
+    { "backAmbientIntensity", nullptr, nullptr },
+    { "backDiffuseColor", nullptr, nullptr },
+    { "backEmissiveColor", nullptr, nullptr },
+    { "backShininess", nullptr, nullptr },
+    { "backSpecularColor", nullptr, nullptr },
+    { "separateBackColor", nullptr, nullptr },
+    { "displayed", nullptr, nullptr },
+    { "clipBoundary", nullptr, nullptr },
+    { "internal", nullptr, nullptr },
+    { "gustiness", nullptr, nullptr },
+    { "turbulence", nullptr, nullptr }
+};
+
+FIVocabulary X3D_vocabulary_3_2 = {
+    nullptr, 0,
+    encodingAlgorithmTable_3_2, 8,
+    nullptr, 0,
+    nullptr, 0,
+    nullptr, 0,
+    nullptr, 0,
+    nullptr, 0,
+    attributeValueTable_3_2, 2,
+    nullptr, 0,
+    nullptr, 0,
+    elementNameTable_3_2, 233,
+    attributeNameTable_3_2, 516
+};
+
+static const char *encodingAlgorithmTable_3_3[] = {
+    "encoder://web3d.org/QuantizedFloatArrayEncoder",
+    "encoder://web3d.org/DeltazlibIntArrayEncoder",
+    "encoder://web3d.org/QuantizedzlibFloatArrayEncoder",
+    "encoder://web3d.org/zlibFloatArrayEncoder",
+    "encoder://web3d.org/QuantizedDoubleArrayEncoder",
+    "encoder://web3d.org/zlibDoubleArrayEncoder",
+    "encoder://web3d.org/QuantizedzlibDoubleArrayEncoder",
+    "encoder://web3d.org/RangeIntArrayEncoder"
+};
+
+static const std::shared_ptr<const FIValue> attributeValueTable_3_3[] = {
+    FIStringValue::create("false"),
+    FIStringValue::create("true")
+};
+
+static const FIQName elementNameTable_3_3[] = {
+    { "Shape", nullptr, nullptr },
+    { "Appearance", nullptr, nullptr },
+    { "Material", nullptr, nullptr },
+    { "IndexedFaceSet", nullptr, nullptr },
+    { "ProtoInstance", nullptr, nullptr },
+    { "Transform", nullptr, nullptr },
+    { "ImageTexture", nullptr, nullptr },
+    { "TextureTransform", nullptr, nullptr },
+    { "Coordinate", nullptr, nullptr },
+    { "Normal", nullptr, nullptr },
+    { "Color", nullptr, nullptr },
+    { "ColorRGBA", nullptr, nullptr },
+    { "TextureCoordinate", nullptr, nullptr },
+    { "ROUTE", nullptr, nullptr },
+    { "fieldValue", nullptr, nullptr },
+    { "Group", nullptr, nullptr },
+    { "LOD", nullptr, nullptr },
+    { "Switch", nullptr, nullptr },
+    { "Script", nullptr, nullptr },
+    { "IndexedTriangleFanSet", nullptr, nullptr },
+    { "IndexedTriangleSet", nullptr, nullptr },
+    { "IndexedTriangleStripSet", nullptr, nullptr },
+    { "MultiTexture", nullptr, nullptr },
+    { "MultiTextureCoordinate", nullptr, nullptr },
+    { "MultiTextureTransform", nullptr, nullptr },
+    { "IndexedLineSet", nullptr, nullptr },
+    { "PointSet", nullptr, nullptr },
+    { "StaticGroup", nullptr, nullptr },
+    { "Sphere", nullptr, nullptr },
+    { "Box", nullptr, nullptr },
+    { "Cone", nullptr, nullptr },
+    { "Anchor", nullptr, nullptr },
+    { "Arc2D", nullptr, nullptr },
+    { "ArcClose2D", nullptr, nullptr },
+    { "AudioClip", nullptr, nullptr },
+    { "Background", nullptr, nullptr },
+    { "Billboard", nullptr, nullptr },
+    { "BooleanFilter", nullptr, nullptr },
+    { "BooleanSequencer", nullptr, nullptr },
+    { "BooleanToggle", nullptr, nullptr },
+    { "BooleanTrigger", nullptr, nullptr },
+    { "Circle2D", nullptr, nullptr },
+    { "Collision", nullptr, nullptr },
+    { "ColorInterpolator", nullptr, nullptr },
+    { "Contour2D", nullptr, nullptr },
+    { "ContourPolyline2D", nullptr, nullptr },
+    { "CoordinateDouble", nullptr, nullptr },
+    { "CoordinateInterpolator", nullptr, nullptr },
+    { "CoordinateInterpolator2D", nullptr, nullptr },
+    { "Cylinder", nullptr, nullptr },
+    { "CylinderSensor", nullptr, nullptr },
+    { "DirectionalLight", nullptr, nullptr },
+    { "Disk2D", nullptr, nullptr },
+    { "EXPORT", nullptr, nullptr },
+    { "ElevationGrid", nullptr, nullptr },
+    { "EspduTransform", nullptr, nullptr },
+    { "ExternProtoDeclare", nullptr, nullptr },
+    { "Extrusion", nullptr, nullptr },
+    { "FillProperties", nullptr, nullptr },
+    { "Fog", nullptr, nullptr },
+    { "FontStyle", nullptr, nullptr },
+    { "GeoCoordinate", nullptr, nullptr },
+    { "GeoElevationGrid", nullptr, nullptr },
+    { "GeoLOD", nullptr, nullptr },
+    { "GeoLocation", nullptr, nullptr },
+    { "GeoMetadata", nullptr, nullptr },
+    { "GeoOrigin", nullptr, nullptr },
+    { "GeoPositionInterpolator", nullptr, nullptr },
+    { "GeoTouchSensor", nullptr, nullptr },
+    { "GeoViewpoint", nullptr, nullptr },
+    { "HAnimDisplacer", nullptr, nullptr },
+    { "HAnimHumanoid", nullptr, nullptr },
+    { "HAnimJoint", nullptr, nullptr },
+    { "HAnimSegment", nullptr, nullptr },
+    { "HAnimSite", nullptr, nullptr },
+    { "IMPORT", nullptr, nullptr },
+    { "IS", nullptr, nullptr },
+    { "Inline", nullptr, nullptr },
+    { "IntegerSequencer", nullptr, nullptr },
+    { "IntegerTrigger", nullptr, nullptr },
+    { "KeySensor", nullptr, nullptr },
+    { "LineProperties", nullptr, nullptr },
+    { "LineSet", nullptr, nullptr },
+    { "LoadSensor", nullptr, nullptr },
+    { "MetadataDouble", nullptr, nullptr },
+    { "MetadataFloat", nullptr, nullptr },
+    { "MetadataInteger", nullptr, nullptr },
+    { "MetadataSet", nullptr, nullptr },
+    { "MetadataString", nullptr, nullptr },
+    { "MovieTexture", nullptr, nullptr },
+    { "NavigationInfo", nullptr, nullptr },
+    { "NormalInterpolator", nullptr, nullptr },
+    { "NurbsCurve", nullptr, nullptr },
+    { "NurbsCurve2D", nullptr, nullptr },
+    { "NurbsOrientationInterpolator", nullptr, nullptr },
+    { "NurbsPatchSurface", nullptr, nullptr },
+    { "NurbsPositionInterpolator", nullptr, nullptr },
+    { "NurbsSet", nullptr, nullptr },
+    { "NurbsSurfaceInterpolator", nullptr, nullptr },
+    { "NurbsSweptSurface", nullptr, nullptr },
+    { "NurbsSwungSurface", nullptr, nullptr },
+    { "NurbsTextureCoordinate", nullptr, nullptr },
+    { "NurbsTrimmedSurface", nullptr, nullptr },
+    { "OrientationInterpolator", nullptr, nullptr },
+    { "PixelTexture", nullptr, nullptr },
+    { "PlaneSensor", nullptr, nullptr },
+    { "PointLight", nullptr, nullptr },
+    { "Polyline2D", nullptr, nullptr },
+    { "Polypoint2D", nullptr, nullptr },
+    { "PositionInterpolator", nullptr, nullptr },
+    { "PositionInterpolator2D", nullptr, nullptr },
+    { "ProtoBody", nullptr, nullptr },
+    { "ProtoDeclare", nullptr, nullptr },
+    { "ProtoInterface", nullptr, nullptr },
+    { "ProximitySensor", nullptr, nullptr },
+    { "ReceiverPdu", nullptr, nullptr },
+    { "Rectangle2D", nullptr, nullptr },
+    { "ScalarInterpolator", nullptr, nullptr },
+    { "Scene", nullptr, nullptr },
+    { "SignalPdu", nullptr, nullptr },
+    { "Sound", nullptr, nullptr },
+    { "SphereSensor", nullptr, nullptr },
+    { "SpotLight", nullptr, nullptr },
+    { "StringSensor", nullptr, nullptr },
+    { "Text", nullptr, nullptr },
+    { "TextureBackground", nullptr, nullptr },
+    { "TextureCoordinateGenerator", nullptr, nullptr },
+    { "TimeSensor", nullptr, nullptr },
+    { "TimeTrigger", nullptr, nullptr },
+    { "TouchSensor", nullptr, nullptr },
+    { "TransmitterPdu", nullptr, nullptr },
+    { "TriangleFanSet", nullptr, nullptr },
+    { "TriangleSet", nullptr, nullptr },
+    { "TriangleSet2D", nullptr, nullptr },
+    { "TriangleStripSet", nullptr, nullptr },
+    { "Viewpoint", nullptr, nullptr },
+    { "VisibilitySensor", nullptr, nullptr },
+    { "WorldInfo", nullptr, nullptr },
+    { "X3D", nullptr, nullptr },
+    { "component", nullptr, nullptr },
+    { "connect", nullptr, nullptr },
+    { "field", nullptr, nullptr },
+    { "head", nullptr, nullptr },
+    { "humanoidBodyType", nullptr, nullptr },
+    { "meta", nullptr, nullptr },
+    { "CADAssembly", nullptr, nullptr },
+    { "CADFace", nullptr, nullptr },
+    { "CADLayer", nullptr, nullptr },
+    { "CADPart", nullptr, nullptr },
+    { "ComposedCubeMapTexture", nullptr, nullptr },
+    { "ComposedShader", nullptr, nullptr },
+    { "ComposedTexture3D", nullptr, nullptr },
+    { "FloatVertexAttribute", nullptr, nullptr },
+    { "FogCoordinate", nullptr, nullptr },
+    { "GeneratedCubeMapTexture", nullptr, nullptr },
+    { "ImageCubeMapTexture", nullptr, nullptr },
+    { "ImageTexture3D", nullptr, nullptr },
+    { "IndexedQuadSet", nullptr, nullptr },
+    { "LocalFog", nullptr, nullptr },
+    { "Matrix3VertexAttribute", nullptr, nullptr },
+    { "Matrix4VertexAttribute", nullptr, nullptr },
+    { "PackagedShader", nullptr, nullptr },
+    { "PixelTexture3D", nullptr, nullptr },
+    { "ProgramShader", nullptr, nullptr },
+    { "QuadSet", nullptr, nullptr },
+    { "ShaderPart", nullptr, nullptr },
+    { "ShaderProgram", nullptr, nullptr },
+    { "TextureCoordinate3D", nullptr, nullptr },
+    { "TextureCoordinate4D", nullptr, nullptr },
+    { "TextureTransform3D", nullptr, nullptr },
+    { "TextureTransformMatrix3D", nullptr, nullptr },
+    { "BallJoint", nullptr, nullptr },
+    { "BoundedPhysicsModel", nullptr, nullptr },
+    { "ClipPlane", nullptr, nullptr },
+    { "CollidableOffset", nullptr, nullptr },
+    { "CollidableShape", nullptr, nullptr },
+    { "CollisionCollection", nullptr, nullptr },
+    { "CollisionSensor", nullptr, nullptr },
+    { "CollisionSpace", nullptr, nullptr },
+    { "ColorDamper", nullptr, nullptr },
+    { "ConeEmitter", nullptr, nullptr },
+    { "Contact", nullptr, nullptr },
+    { "CoordinateDamper", nullptr, nullptr },
+    { "DISEntityManager", nullptr, nullptr },
+    { "DISEntityTypeMapping", nullptr, nullptr },
+    { "DoubleAxisHingeJoint", nullptr, nullptr },
+    { "EaseInEaseOut", nullptr, nullptr },
+    { "ExplosionEmitter", nullptr, nullptr },
+    { "ForcePhysicsModel", nullptr, nullptr },
+    { "GeoProximitySensor", nullptr, nullptr },
+    { "GeoTransform", nullptr, nullptr },
+    { "Layer", nullptr, nullptr },
+    { "LayerSet", nullptr, nullptr },
+    { "Layout", nullptr, nullptr },
+    { "LayoutGroup", nullptr, nullptr },
+    { "LayoutLayer", nullptr, nullptr },
+    { "LinePickSensor", nullptr, nullptr },
+    { "MotorJoint", nullptr, nullptr },
+    { "OrientationChaser", nullptr, nullptr },
+    { "OrientationDamper", nullptr, nullptr },
+    { "OrthoViewpoint", nullptr, nullptr },
+    { "ParticleSystem", nullptr, nullptr },
+    { "PickableGroup", nullptr, nullptr },
+    { "PointEmitter", nullptr, nullptr },
+    { "PointPickSensor", nullptr, nullptr },
+    { "PolylineEmitter", nullptr, nullptr },
+    { "PositionChaser", nullptr, nullptr },
+    { "PositionChaser2D", nullptr, nullptr },
+    { "PositionDamper", nullptr, nullptr },
+    { "PositionDamper2D", nullptr, nullptr },
+    { "PrimitivePickSensor", nullptr, nullptr },
+    { "RigidBody", nullptr, nullptr },
+    { "RigidBodyCollection", nullptr, nullptr },
+    { "ScalarChaser", nullptr, nullptr },
+    { "ScreenFontStyle", nullptr, nullptr },
+    { "ScreenGroup", nullptr, nullptr },
+    { "SingleAxisHingeJoint", nullptr, nullptr },
+    { "SliderJoint", nullptr, nullptr },
+    { "SplinePositionInterpolator", nullptr, nullptr },
+    { "SplinePositionInterpolator2D", nullptr, nullptr },
+    { "SplineScalarInterpolator", nullptr, nullptr },
+    { "SquadOrientationInterpolator", nullptr, nullptr },
+    { "SurfaceEmitter", nullptr, nullptr },
+    { "TexCoordDamper2D", nullptr, nullptr },
+    { "TextureProperties", nullptr, nullptr },
+    { "TransformSensor", nullptr, nullptr },
+    { "TwoSidedMaterial", nullptr, nullptr },
+    { "UniversalJoint", nullptr, nullptr },
+    { "ViewpointGroup", nullptr, nullptr },
+    { "Viewport", nullptr, nullptr },
+    { "VolumeEmitter", nullptr, nullptr },
+    { "VolumePickSensor", nullptr, nullptr },
+    { "WindPhysicsModel", nullptr, nullptr },
+    { "BlendedVolumeStyle", nullptr, nullptr },
+    { "BoundaryEnhancementVolumeStyle", nullptr, nullptr },
+    { "CartoonVolumeStyle", nullptr, nullptr },
+    { "ComposedVolumeStyle", nullptr, nullptr },
+    { "EdgeEnhancementVolumeStyle", nullptr, nullptr },
+    { "IsoSurfaceVolumeData", nullptr, nullptr },
+    { "MetadataBoolean", nullptr, nullptr },
+    { "OpacityMapVolumeStyle", nullptr, nullptr },
+    { "ProjectionVolumeStyle", nullptr, nullptr },
+    { "SegmentedVolumeData", nullptr, nullptr },
+    { "ShadedVolumeStyle", nullptr, nullptr },
+    { "SilhouetteEnhancementVolumeStyle", nullptr, nullptr },
+    { "ToneMappedVolumeStyle", nullptr, nullptr },
+    { "VolumeData", nullptr, nullptr },
+    { "ColorChaser", nullptr, nullptr },
+    { "CoordinateChaser", nullptr, nullptr },
+    { "ScalarDamper", nullptr, nullptr },
+    { "TexCoordChaser2D", nullptr, nullptr },
+    { "unit", nullptr, nullptr }
+};
+
+static const FIQName attributeNameTable_3_3[] = {
+    { "DEF", nullptr, nullptr },
+    { "USE", nullptr, nullptr },
+    { "containerField", nullptr, nullptr },
+    { "fromNode", nullptr, nullptr },
+    { "fromField", nullptr, nullptr },
+    { "toNode", nullptr, nullptr },
+    { "toField", nullptr, nullptr },
+    { "name", nullptr, nullptr },
+    { "value", nullptr, nullptr },
+    { "color", nullptr, nullptr },
+    { "colorIndex", nullptr, nullptr },
+    { "coordIndex", nullptr, nullptr },
+    { "texCoordIndex", nullptr, nullptr },
+    { "normalIndex", nullptr, nullptr },
+    { "colorPerVertex", nullptr, nullptr },
+    { "normalPerVertex", nullptr, nullptr },
+    { "rotation", nullptr, nullptr },
+    { "scale", nullptr, nullptr },
+    { "center", nullptr, nullptr },
+    { "scaleOrientation", nullptr, nullptr },
+    { "translation", nullptr, nullptr },
+    { "url", nullptr, nullptr },
+    { "repeatS", nullptr, nullptr },
+    { "repeatT", nullptr, nullptr },
+    { "point", nullptr, nullptr },
+    { "vector", nullptr, nullptr },
+    { "range", nullptr, nullptr },
+    { "ambientIntensity", nullptr, nullptr },
+    { "diffuseColor", nullptr, nullptr },
+    { "emissiveColor", nullptr, nullptr },
+    { "shininess", nullptr, nullptr },
+    { "specularColor", nullptr, nullptr },
+    { "transparency", nullptr, nullptr },
+    { "whichChoice", nullptr, nullptr },
+    { "index", nullptr, nullptr },
+    { "mode", nullptr, nullptr },
+    { "source", nullptr, nullptr },
+    { "function", nullptr, nullptr },
+    { "alpha", nullptr, nullptr },
+    { "vertexCount", nullptr, nullptr },
+    { "radius", nullptr, nullptr },
+    { "size", nullptr, nullptr },
+    { "height", nullptr, nullptr },
+    { "solid", nullptr, nullptr },
+    { "ccw", nullptr, nullptr },
+    { "key", nullptr, nullptr },
+    { "keyValue", nullptr, nullptr },
+    { "enabled", nullptr, nullptr },
+    { "direction", nullptr, nullptr },
+    { "position", nullptr, nullptr },
+    { "orientation", nullptr, nullptr },
+    { "bboxCenter", nullptr, nullptr },
+    { "bboxSize", nullptr, nullptr },
+    { "AS", nullptr, nullptr },
+    { "InlineDEF", nullptr, nullptr },
+    { "accessType", nullptr, nullptr },
+    { "actionKeyPress", nullptr, nullptr },
+    { "actionKeyRelease", nullptr, nullptr },
+    { "address", nullptr, nullptr },
+    { "altKey", nullptr, nullptr },
+    { "antennaLocation", nullptr, nullptr },
+    { "antennaPatternLength", nullptr, nullptr },
+    { "antennaPatternType", nullptr, nullptr },
+    { "applicationID", nullptr, nullptr },
+    { "articulationParameterArray", nullptr, nullptr },
+    { "articulationParameterChangeIndicatorArray", nullptr, nullptr },
+    { "articulationParameterCount", nullptr, nullptr },
+    { "articulationParameterDesignatorArray", nullptr, nullptr },
+    { "articulationParameterIdPartAttachedArray", nullptr, nullptr },
+    { "articulationParameterTypeArray", nullptr, nullptr },
+    { "attenuation", nullptr, nullptr },
+    { "autoOffset", nullptr, nullptr },
+    { "avatarSize", nullptr, nullptr },
+    { "axisOfRotation", nullptr, nullptr },
+    { "backUrl", nullptr, nullptr },
+    { "beamWidth", nullptr, nullptr },
+    { "beginCap", nullptr, nullptr },
+    { "bindTime", nullptr, nullptr },
+    { "bottom", nullptr, nullptr },
+    { "bottomRadius", nullptr, nullptr },
+    { "bottomUrl", nullptr, nullptr },
+    { "centerOfMass", nullptr, nullptr },
+    { "centerOfRotation", nullptr, nullptr },
+    { "child1Url", nullptr, nullptr },
+    { "child2Url", nullptr, nullptr },
+    { "child3Url", nullptr, nullptr },
+    { "child4Url", nullptr, nullptr },
+    { "class", nullptr, nullptr },
+    { "closureType", nullptr, nullptr },
+    { "collideTime", nullptr, nullptr },
+    { "content", nullptr, nullptr },
+    { "controlKey", nullptr, nullptr },
+    { "controlPoint", nullptr, nullptr },
+    { "convex", nullptr, nullptr },
+    { "coordinateSystem", nullptr, nullptr },
+    { "copyright", nullptr, nullptr },
+    { "creaseAngle", nullptr, nullptr },
+    { "crossSection", nullptr, nullptr },
+    { "cryptoKeyID", nullptr, nullptr },
+    { "cryptoSystem", nullptr, nullptr },
+    { "cutOffAngle", nullptr, nullptr },
+    { "cycleInterval", nullptr, nullptr },
+    { "cycleTime", nullptr, nullptr },
+    { "data", nullptr, nullptr },
+    { "dataFormat", nullptr, nullptr },
+    { "dataLength", nullptr, nullptr },
+    { "dataUrl", nullptr, nullptr },
+    { "date", nullptr, nullptr },
+    { "deadReckoning", nullptr, nullptr },
+    { "deletionAllowed", nullptr, nullptr },
+    { "description", nullptr, nullptr },
+    { "detonateTime", nullptr, nullptr },
+    { "dir", nullptr, nullptr },
+    { "directOutput", nullptr, nullptr },
+    { "diskAngle", nullptr, nullptr },
+    { "displacements", nullptr, nullptr },
+    { "documentation", nullptr, nullptr },
+    { "elapsedTime", nullptr, nullptr },
+    { "ellipsoid", nullptr, nullptr },
+    { "encodingScheme", nullptr, nullptr },
+    { "endAngle", nullptr, nullptr },
+    { "endCap", nullptr, nullptr },
+    { "enterTime", nullptr, nullptr },
+    { "enteredText", nullptr, nullptr },
+    { "entityCategory", nullptr, nullptr },
+    { "entityCountry", nullptr, nullptr },
+    { "entityDomain", nullptr, nullptr },
+    { "entityExtra", nullptr, nullptr },
+    { "entityID", nullptr, nullptr },
+    { "entityKind", nullptr, nullptr },
+    { "entitySpecific", nullptr, nullptr },
+    { "entitySubCategory", nullptr, nullptr },
+    { "exitTime", nullptr, nullptr },
+    { "extent", nullptr, nullptr },
+    { "family", nullptr, nullptr },
+    { "fanCount", nullptr, nullptr },
+    { "fieldOfView", nullptr, nullptr },
+    { "filled", nullptr, nullptr },
+    { "finalText", nullptr, nullptr },
+    { "fireMissionIndex", nullptr, nullptr },
+    { "fired1", nullptr, nullptr },
+    { "fired2", nullptr, nullptr },
+    { "firedTime", nullptr, nullptr },
+    { "firingRange", nullptr, nullptr },
+    { "firingRate", nullptr, nullptr },
+    { "fogType", nullptr, nullptr },
+    { "forceID", nullptr, nullptr },
+    { "frequency", nullptr, nullptr },
+    { "frontUrl", nullptr, nullptr },
+    { "fuse", nullptr, nullptr },
+    { "geoCoords", nullptr, nullptr },
+    { "geoGridOrigin", nullptr, nullptr },
+    { "geoSystem", nullptr, nullptr },
+    { "groundAngle", nullptr, nullptr },
+    { "groundColor", nullptr, nullptr },
+    { "hatchColor", nullptr, nullptr },
+    { "hatchStyle", nullptr, nullptr },
+    { "hatched", nullptr, nullptr },
+    { "headlight", nullptr, nullptr },
+    { "horizontal", nullptr, nullptr },
+    { "horizontalDatum", nullptr, nullptr },
+    { "http-equiv", nullptr, nullptr },
+    { "image", nullptr, nullptr },
+    { "importedDEF", nullptr, nullptr },
+    { "info", nullptr, nullptr },
+    { "innerRadius", nullptr, nullptr },
+    { "inputFalse", nullptr, nullptr },
+    { "inputNegate", nullptr, nullptr },
+    { "inputSource", nullptr, nullptr },
+    { "inputTrue", nullptr, nullptr },
+    { "integerKey", nullptr, nullptr },
+    { "intensity", nullptr, nullptr },
+    { "jump", nullptr, nullptr },
+    { "justify", nullptr, nullptr },
+    { "keyPress", nullptr, nullptr },
+    { "keyRelease", nullptr, nullptr },
+    { "knot", nullptr, nullptr },
+    { "lang", nullptr, nullptr },
+    { "language", nullptr, nullptr },
+    { "leftToRight", nullptr, nullptr },
+    { "leftUrl", nullptr, nullptr },
+    { "length", nullptr, nullptr },
+    { "lengthOfModulationParameters", nullptr, nullptr },
+    { "level", nullptr, nullptr },
+    { "limitOrientation", nullptr, nullptr },
+    { "lineSegments", nullptr, nullptr },
+    { "linearAcceleration", nullptr, nullptr },
+    { "linearVelocity", nullptr, nullptr },
+    { "linetype", nullptr, nullptr },
+    { "linewidthScaleFactor", nullptr, nullptr },
+    { "llimit", nullptr, nullptr },
+    { "load", nullptr, nullptr },
+    { "loadTime", nullptr, nullptr },
+    { "localDEF", nullptr, nullptr },
+    { "location", nullptr, nullptr },
+    { "loop", nullptr, nullptr },
+    { "marking", nullptr, nullptr },
+    { "mass", nullptr, nullptr },
+    { "maxAngle", nullptr, nullptr },
+    { "maxBack", nullptr, nullptr },
+    { "maxExtent", nullptr, nullptr },
+    { "maxFront", nullptr, nullptr },
+    { "maxPosition", nullptr, nullptr },
+    { "metadataFormat", nullptr, nullptr },
+    { "minAngle", nullptr, nullptr },
+    { "minBack", nullptr, nullptr },
+    { "minFront", nullptr, nullptr },
+    { "minPosition", nullptr, nullptr },
+    { "modulationTypeDetail", nullptr, nullptr },
+    { "modulationTypeMajor", nullptr, nullptr },
+    { "modulationTypeSpreadSpectrum", nullptr, nullptr },
+    { "modulationTypeSystem", nullptr, nullptr },
+    { "momentsOfInertia", nullptr, nullptr },
+    { "multicastRelayHost", nullptr, nullptr },
+    { "multicastRelayPort", nullptr, nullptr },
+    { "munitionApplicationID", nullptr, nullptr },
+    { "munitionEndPoint", nullptr, nullptr },
+    { "munitionEntityID", nullptr, nullptr },
+    { "munitionQuantity", nullptr, nullptr },
+    { "munitionSiteID", nullptr, nullptr },
+    { "munitionStartPoint", nullptr, nullptr },
+    { "mustEvaluate", nullptr, nullptr },
+    { "navType", nullptr, nullptr },
+    { "networkMode", nullptr, nullptr },
+    { "next", nullptr, nullptr },
+    { "nodeField", nullptr, nullptr },
+    { "offset", nullptr, nullptr },
+    { "on", nullptr, nullptr },
+    { "order", nullptr, nullptr },
+    { "originator", nullptr, nullptr },
+    { "outerRadius", nullptr, nullptr },
+    { "parameter", nullptr, nullptr },
+    { "pauseTime", nullptr, nullptr },
+    { "pitch", nullptr, nullptr },
+    { "points", nullptr, nullptr },
+    { "port", nullptr, nullptr },
+    { "power", nullptr, nullptr },
+    { "previous", nullptr, nullptr },
+    { "priority", nullptr, nullptr },
+    { "profile", nullptr, nullptr },
+    { "progress", nullptr, nullptr },
+    { "protoField", nullptr, nullptr },
+    { "radioEntityTypeCategory", nullptr, nullptr },
+    { "radioEntityTypeCountry", nullptr, nullptr },
+    { "radioEntityTypeDomain", nullptr, nullptr },
+    { "radioEntityTypeKind", nullptr, nullptr },
+    { "radioEntityTypeNomenclature", nullptr, nullptr },
+    { "radioEntityTypeNomenclatureVersion", nullptr, nullptr },
+    { "radioID", nullptr, nullptr },
+    { "readInterval", nullptr, nullptr },
+    { "receivedPower", nullptr, nullptr },
+    { "receiverState", nullptr, nullptr },
+    { "reference", nullptr, nullptr },
+    { "relativeAntennaLocation", nullptr, nullptr },
+    { "resolution", nullptr, nullptr },
+    { "resumeTime", nullptr, nullptr },
+    { "rightUrl", nullptr, nullptr },
+    { "rootUrl", nullptr, nullptr },
+    { "rotateYUp", nullptr, nullptr },
+    { "rtpHeaderExpected", nullptr, nullptr },
+    { "sampleRate", nullptr, nullptr },
+    { "samples", nullptr, nullptr },
+    { "shiftKey", nullptr, nullptr },
+    { "side", nullptr, nullptr },
+    { "siteID", nullptr, nullptr },
+    { "skinCoordIndex", nullptr, nullptr },
+    { "skinCoordWeight", nullptr, nullptr },
+    { "skyAngle", nullptr, nullptr },
+    { "skyColor", nullptr, nullptr },
+    { "spacing", nullptr, nullptr },
+    { "spatialize", nullptr, nullptr },
+    { "speed", nullptr, nullptr },
+    { "speedFactor", nullptr, nullptr },
+    { "spine", nullptr, nullptr },
+    { "startAngle", nullptr, nullptr },
+    { "startTime", nullptr, nullptr },
+    { "stiffness", nullptr, nullptr },
+    { "stopTime", nullptr, nullptr },
+    { "string", nullptr, nullptr },
+    { "stripCount", nullptr, nullptr },
+    { "style", nullptr, nullptr },
+    { "summary", nullptr, nullptr },
+    { "tdlType", nullptr, nullptr },
+    { "tessellation", nullptr, nullptr },
+    { "tessellationScale", nullptr, nullptr },
+    { "time", nullptr, nullptr },
+    { "timeOut", nullptr, nullptr },
+    { "timestamp", nullptr, nullptr },
+    { "title", nullptr, nullptr },
+    { "toggle", nullptr, nullptr },
+    { "top", nullptr, nullptr },
+    { "topToBottom", nullptr, nullptr },
+    { "topUrl", nullptr, nullptr },
+    { "touchTime", nullptr, nullptr },
+    { "transmitFrequencyBandwidth", nullptr, nullptr },
+    { "transmitState", nullptr, nullptr },
+    { "transmitterApplicationID", nullptr, nullptr },
+    { "transmitterEntityID", nullptr, nullptr },
+    { "transmitterRadioID", nullptr, nullptr },
+    { "transmitterSiteID", nullptr, nullptr },
+    { "transparent", nullptr, nullptr },
+    { "triggerTime", nullptr, nullptr },
+    { "triggerTrue", nullptr, nullptr },
+    { "triggerValue", nullptr, nullptr },
+    { "type", nullptr, nullptr },
+    { "uDimension", nullptr, nullptr },
+    { "uKnot", nullptr, nullptr },
+    { "uOrder", nullptr, nullptr },
+    { "uTessellation", nullptr, nullptr },
+    { "ulimit", nullptr, nullptr },
+    { "vDimension", nullptr, nullptr },
+    { "vKnot", nullptr, nullptr },
+    { "vOrder", nullptr, nullptr },
+    { "vTessellation", nullptr, nullptr },
+    { "version", nullptr, nullptr },
+    { "verticalDatum", nullptr, nullptr },
+    { "vertices", nullptr, nullptr },
+    { "visibilityLimit", nullptr, nullptr },
+    { "visibilityRange", nullptr, nullptr },
+    { "warhead", nullptr, nullptr },
+    { "weight", nullptr, nullptr },
+    { "whichGeometry", nullptr, nullptr },
+    { "writeInterval", nullptr, nullptr },
+    { "xDimension", nullptr, nullptr },
+    { "xSpacing", nullptr, nullptr },
+    { "yScale", nullptr, nullptr },
+    { "zDimension", nullptr, nullptr },
+    { "zSpacing", nullptr, nullptr },
+    { "visible", nullptr, nullptr },
+    { "repeatR", nullptr, nullptr },
+    { "texture", nullptr, nullptr },
+    { "back", nullptr, nullptr },
+    { "front", nullptr, nullptr },
+    { "left", nullptr, nullptr },
+    { "right", nullptr, nullptr },
+    { "parts", nullptr, nullptr },
+    { "isSelected", nullptr, nullptr },
+    { "isValid", nullptr, nullptr },
+    { "numComponents", nullptr, nullptr },
+    { "depth", nullptr, nullptr },
+    { "update", nullptr, nullptr },
+    { "fogCoord", nullptr, nullptr },
+    { "texCoord", nullptr, nullptr },
+    { "activate", nullptr, nullptr },
+    { "programs", nullptr, nullptr },
+    { "matrix", nullptr, nullptr },
+    { "anchorPoint", nullptr, nullptr },
+    { "body1", nullptr, nullptr },
+    { "body2", nullptr, nullptr },
+    { "forceOutput", nullptr, nullptr },
+    { "body1AnchorPoint", nullptr, nullptr },
+    { "body2AnchorPoint", nullptr, nullptr },
+    { "plane", nullptr, nullptr },
+    { "appliedParameters", nullptr, nullptr },
+    { "bounce", nullptr, nullptr },
+    { "frictionCoefficients", nullptr, nullptr },
+    { "minBounceSpeed", nullptr, nullptr },
+    { "slipFactors", nullptr, nullptr },
+    { "softnessConstantForceMix", nullptr, nullptr },
+    { "softnessErrorCorrection", nullptr, nullptr },
+    { "surfaceSpeed", nullptr, nullptr },
+    { "isActive", nullptr, nullptr },
+    { "useGeometry", nullptr, nullptr },
+    { "set_destination", nullptr, nullptr },
+    { "set_value", nullptr, nullptr },
+    { "tau", nullptr, nullptr },
+    { "tolerance", nullptr, nullptr },
+    { "value_changed", nullptr, nullptr },
+    { "initialDestination", nullptr, nullptr },
+    { "initialValue", nullptr, nullptr },
+    { "angle", nullptr, nullptr },
+    { "variation", nullptr, nullptr },
+    { "surfaceArea", nullptr, nullptr },
+    { "frictionDirection", nullptr, nullptr },
+    { "slipCoefficients", nullptr, nullptr },
+    { "category", nullptr, nullptr },
+    { "country", nullptr, nullptr },
+    { "domain", nullptr, nullptr },
+    { "extra", nullptr, nullptr },
+    { "kind", nullptr, nullptr },
+    { "specific", nullptr, nullptr },
+    { "subcategory", nullptr, nullptr },
+    { "axis1", nullptr, nullptr },
+    { "axis2", nullptr, nullptr },
+    { "desiredAngularVelocity1", nullptr, nullptr },
+    { "desiredAngularVelocity2", nullptr, nullptr },
+    { "maxAngle1", nullptr, nullptr },
+    { "maxTorque1", nullptr, nullptr },
+    { "maxTorque2", nullptr, nullptr },
+    { "minAngle1", nullptr, nullptr },
+    { "stopBounce1", nullptr, nullptr },
+    { "stopConstantForceMix1", nullptr, nullptr },
+    { "stopErrorCorrection1", nullptr, nullptr },
+    { "suspensionErrorCorrection", nullptr, nullptr },
+    { "suspensionForce", nullptr, nullptr },
+    { "body1Axis", nullptr, nullptr },
+    { "body2Axis", nullptr, nullptr },
+    { "hinge1Angle", nullptr, nullptr },
+    { "hinge1AngleRate", nullptr, nullptr },
+    { "hinge2Angle", nullptr, nullptr },
+    { "hinge2AngleRate", nullptr, nullptr },
+    { "set_fraction", nullptr, nullptr },
+    { "easeInEaseOut", nullptr, nullptr },
+    { "modifiedFraction_changed", nullptr, nullptr },
+    { "force", nullptr, nullptr },
+    { "geoCenter", nullptr, nullptr },
+    { "centerOfRotation_changed", nullptr, nullptr },
+    { "geoCoord_changed", nullptr, nullptr },
+    { "orientation_changed", nullptr, nullptr },
+    { "position_changed", nullptr, nullptr },
+    { "isPickable", nullptr, nullptr },
+    { "viewport", nullptr, nullptr },
+    { "activeLayer", nullptr, nullptr },
+    { "align", nullptr, nullptr },
+    { "offsetUnits", nullptr, nullptr },
+    { "scaleMode", nullptr, nullptr },
+    { "sizeUnits", nullptr, nullptr },
+    { "layout", nullptr, nullptr },
+    { "objectType", nullptr, nullptr },
+    { "pickedNormal", nullptr, nullptr },
+    { "pickedPoint", nullptr, nullptr },
+    { "pickedTextureCoordinate", nullptr, nullptr },
+    { "intersectionType", nullptr, nullptr },
+    { "sortOrder", nullptr, nullptr },
+    { "axis1Angle", nullptr, nullptr },
+    { "axis1Torque", nullptr, nullptr },
+    { "axis2Angle", nullptr, nullptr },
+    { "axis2Torque", nullptr, nullptr },
+    { "axis3Angle", nullptr, nullptr },
+    { "axis3Torque", nullptr, nullptr },
+    { "enabledAxies", nullptr, nullptr },
+    { "motor1Axis", nullptr, nullptr },
+    { "motor2Axis", nullptr, nullptr },
+    { "motor3Axis", nullptr, nullptr },
+    { "stop1Bounce", nullptr, nullptr },
+    { "stop1ErrorCorrection", nullptr, nullptr },
+    { "stop2Bounce", nullptr, nullptr },
+    { "stop2ErrorCorrection", nullptr, nullptr },
+    { "stop3Bounce", nullptr, nullptr },
+    { "stop3ErrorCorrection", nullptr, nullptr },
+    { "motor1Angle", nullptr, nullptr },
+    { "motor1AngleRate", nullptr, nullptr },
+    { "motor2Angle", nullptr, nullptr },
+    { "motor2AngleRate", nullptr, nullptr },
+    { "motor3Angle", nullptr, nullptr },
+    { "motor3AngleRate", nullptr, nullptr },
+    { "autoCalc", nullptr, nullptr },
+    { "duration", nullptr, nullptr },
+    { "retainUserOffsets", nullptr, nullptr },
+    { "isBound", nullptr, nullptr },
+    { "appearance", nullptr, nullptr },
+    { "createParticles", nullptr, nullptr },
+    { "lifetimeVariation", nullptr, nullptr },
+    { "maxParticles", nullptr, nullptr },
+    { "particleLifetime", nullptr, nullptr },
+    { "particleSize", nullptr, nullptr },
+    { "colorKey", nullptr, nullptr },
+    { "geometryType", nullptr, nullptr },
+    { "texCoordKey", nullptr, nullptr },
+    { "pickable", nullptr, nullptr },
+    { "angularDampingFactor", nullptr, nullptr },
+    { "angularVelocity", nullptr, nullptr },
+    { "autoDamp", nullptr, nullptr },
+    { "autoDisable", nullptr, nullptr },
+    { "disableAngularSpeed", nullptr, nullptr },
+    { "disableLinearSpeed", nullptr, nullptr },
+    { "disableTime", nullptr, nullptr },
+    { "finiteRotationAxis", nullptr, nullptr },
+    { "fixed", nullptr, nullptr },
+    { "forces", nullptr, nullptr },
+    { "inertia", nullptr, nullptr },
+    { "linearDampingFactor", nullptr, nullptr },
+    { "torques", nullptr, nullptr },
+    { "useFiniteRotation", nullptr, nullptr },
+    { "useGlobalForce", nullptr, nullptr },
+    { "constantForceMix", nullptr, nullptr },
+    { "constantSurfaceThickness", nullptr, nullptr },
+    { "errorCorrection", nullptr, nullptr },
+    { "iterations", nullptr, nullptr },
+    { "maxCorrectionSpeed", nullptr, nullptr },
+    { "preferAccuracy", nullptr, nullptr },
+    { "pointSize", nullptr, nullptr },
+    { "stopBounce", nullptr, nullptr },
+    { "stopErrorCorrection", nullptr, nullptr },
+    { "angleRate", nullptr, nullptr },
+    { "maxSeparation", nullptr, nullptr },
+    { "minSeparation", nullptr, nullptr },
+    { "separation", nullptr, nullptr },
+    { "separationRate", nullptr, nullptr },
+    { "closed", nullptr, nullptr },
+    { "keyVelocity", nullptr, nullptr },
+    { "normalizeVelocity", nullptr, nullptr },
+    { "surface", nullptr, nullptr },
+    { "anisotropicDegree", nullptr, nullptr },
+    { "borderColor", nullptr, nullptr },
+    { "borderWidth", nullptr, nullptr },
+    { "boundaryModeS", nullptr, nullptr },
+    { "boundaryModeT", nullptr, nullptr },
+    { "boundaryModeR", nullptr, nullptr },
+    { "magnificationFilter", nullptr, nullptr },
+    { "minificationFilter", nullptr, nullptr },
+    { "textureCompression", nullptr, nullptr },
+    { "texturePriority", nullptr, nullptr },
+    { "generateMipMaps", nullptr, nullptr },
+    { "targetObject", nullptr, nullptr },
+    { "backAmbientIntensity", nullptr, nullptr },
+    { "backDiffuseColor", nullptr, nullptr },
+    { "backEmissiveColor", nullptr, nullptr },
+    { "backShininess", nullptr, nullptr },
+    { "backSpecularColor", nullptr, nullptr },
+    { "separateBackColor", nullptr, nullptr },
+    { "displayed", nullptr, nullptr },
+    { "clipBoundary", nullptr, nullptr },
+    { "internal", nullptr, nullptr },
+    { "gustiness", nullptr, nullptr },
+    { "turbulence", nullptr, nullptr },
+    { "unitCategory", nullptr, nullptr },
+    { "unitName", nullptr, nullptr },
+    { "unitConversionFactor", nullptr, nullptr },
+    { "weightConstant1", nullptr, nullptr },
+    { "weightConstant2", nullptr, nullptr },
+    { "weightFunction1", nullptr, nullptr },
+    { "weightFunction2", nullptr, nullptr },
+    { "boundaryOpacity", nullptr, nullptr },
+    { "opacityFactor", nullptr, nullptr },
+    { "retainedOpacity", nullptr, nullptr },
+    { "colorSteps", nullptr, nullptr },
+    { "orthogonalColor", nullptr, nullptr },
+    { "parallelColor", nullptr, nullptr },
+    { "ordered", nullptr, nullptr },
+    { "edgeColor", nullptr, nullptr },
+    { "gradientThreshold", nullptr, nullptr },
+    { "contourStepSize", nullptr, nullptr },
+    { "dimensions", nullptr, nullptr },
+    { "surfaceTolerance", nullptr, nullptr },
+    { "surfaceValues", nullptr, nullptr },
+    { "intensityThreshold", nullptr, nullptr },
+    { "segmentEnabled", nullptr, nullptr },
+    { "lighting", nullptr, nullptr },
+    { "shadows", nullptr, nullptr },
+    { "phaseFunction", nullptr, nullptr },
+    { "silhouetteBoundaryOpacity", nullptr, nullptr },
+    { "silhouetteRetainedOpacity", nullptr, nullptr },
+    { "silhouetteSharpness", nullptr, nullptr },
+    { "coolColor", nullptr, nullptr },
+    { "warmColor", nullptr, nullptr }
+};
+
+FIVocabulary X3D_vocabulary_3_3 = {
+    nullptr, 0,
+    encodingAlgorithmTable_3_3, 8,
+    nullptr, 0,
+    nullptr, 0,
+    nullptr, 0,
+    nullptr, 0,
+    nullptr, 0,
+    attributeValueTable_3_3, 2,
+    nullptr, 0,
+    nullptr, 0,
+    elementNameTable_3_3, 252,
+    attributeNameTable_3_3, 546
+};
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 2 - 1
code/XFileExporter.cpp

@@ -43,12 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_X_EXPORTER
 #ifndef ASSIMP_BUILD_NO_X_EXPORTER
+
 #include "XFileExporter.h"
 #include "XFileExporter.h"
 #include "ConvertToLHProcess.h"
 #include "ConvertToLHProcess.h"
 #include "Bitmap.h"
 #include "Bitmap.h"
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/DefaultIOSystem.h>
 #include <ctime>
 #include <ctime>
 #include <set>
 #include <set>

+ 2 - 1
code/XFileImporter.cpp

@@ -237,8 +237,9 @@ aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFil
 // Creates the meshes for the given node.
 // Creates the meshes for the given node.
 void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes)
 void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes)
 {
 {
-    if( pMeshes.size() == 0)
+    if (pMeshes.empty()) {
         return;
         return;
+    }
 
 
     // create a mesh for each mesh-material combination in the source node
     // create a mesh for each mesh-material combination in the source node
     std::vector<aiMesh*> meshes;
     std::vector<aiMesh*> meshes;

+ 4 - 7
code/XFileParser.cpp

@@ -466,15 +466,12 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh)
     pMesh->mPosFaces.resize( numPosFaces);
     pMesh->mPosFaces.resize( numPosFaces);
     for( unsigned int a = 0; a < numPosFaces; a++)
     for( unsigned int a = 0; a < numPosFaces; a++)
     {
     {
-        unsigned int numIndices = ReadInt();
-        if( numIndices < 3) {
-            ThrowException( format() << "Invalid index count " << numIndices << " for face " << a << "." );
-        }
-
         // read indices
         // read indices
+        unsigned int numIndices = ReadInt();
         Face& face = pMesh->mPosFaces[a];
         Face& face = pMesh->mPosFaces[a];
-        for( unsigned int b = 0; b < numIndices; b++)
-            face.mIndices.push_back( ReadInt());
+        for (unsigned int b = 0; b < numIndices; b++) {
+            face.mIndices.push_back( ReadInt() );
+        }
         TestForSeparator();
         TestForSeparator();
     }
     }
 
 

+ 5 - 2
code/glTFExporter.cpp

@@ -48,8 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ByteSwapper.h"
 #include "ByteSwapper.h"
 
 
 #include "SplitLargeMeshes.h"
 #include "SplitLargeMeshes.h"
-#include "SceneCombiner.h"
 
 
+#include <assimp/SceneCombiner.h>
 #include <assimp/version.h>
 #include <assimp/version.h>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/Exporter.hpp>
 #include <assimp/Exporter.hpp>
@@ -185,8 +185,11 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     unsigned int bytesPerComp = ComponentTypeSize(compType);
     unsigned int bytesPerComp = ComponentTypeSize(compType);
 
 
     size_t offset = buffer->byteLength;
     size_t offset = buffer->byteLength;
+    // make sure offset is correctly byte-aligned, as required by spec
+    size_t padding = offset % bytesPerComp;
+    offset += padding;
     size_t length = count * numCompsOut * bytesPerComp;
     size_t length = count * numCompsOut * bytesPerComp;
-    buffer->Grow(length);
+    buffer->Grow(length + padding);
 
 
     // bufferView
     // bufferView
     Ref<BufferView> bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view"));
     Ref<BufferView> bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view"));

+ 114 - 8
contrib/openddlparser/CMakeLists.txt

@@ -3,18 +3,40 @@ PROJECT( OpenDDL-Parser )
 SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
 SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
 SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
 SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
 SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
 SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
-SET ( OPENDDL_PARSER_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} )
+SET ( OPENDDL_PARSER_VERSION ${OPENDDL_PARSER_VERSION_MAJOR}.${OPENDDL_PARSER_VERSION_MINOR}.${OPENDDL_PARSER_VERSION_PATCH} )
 SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
 SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
 
 
+option( DDL_USE_CPP11           "Set to ON to use C++11 features ( always on on windows )."                   ON )
+option( DDL_DEBUG_OUTPUT        "Set to ON to use output debug texts"                                         OFF )
+option( DDL_STATIC_LIBRARY		"Set to ON to build static libary of OpenDDL Parser."                         ON )
+option( COVERALLS               "Generate coveralls data"                                                     OFF )
+
+if ( DDL_USE_CPP11 )
+    if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+        set( OPENDDL_CXXFLAGS -std=c++0x )
+    elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+        set( OPENDDL_CXXFLAGS --std=c++11 )
+    endif()
+else( DDL_USE_CPP11 )
+    add_definitions( -DOPENDDL_NO_USE_CPP11 )
+endif( DDL_USE_CPP11)
+
 if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
 if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
     find_package(Threads)
     find_package(Threads)
 else()
 else()
     add_definitions( -D_CRT_SECURE_NO_WARNINGS )
     add_definitions( -D_CRT_SECURE_NO_WARNINGS )
 endif()
 endif()
 
 
+if ( DDL_STATIC_LIBRARY )
+	add_definitions( -DOPENDDL_STATIC_LIBARY )
+endif()
+
 add_definitions( -DOPENDDLPARSER_BUILD )
 add_definitions( -DOPENDDLPARSER_BUILD )
-add_definitions( -DOPENDDL_NO_USE_CPP11 )
 add_definitions( -D_VARIADIC_MAX=10 )
 add_definitions( -D_VARIADIC_MAX=10 )
+add_definitions( -DGTEST_HAS_PTHREAD=0 )
+if ( DDL_DEBUG_OUTPUT )
+    add_definitions( -DDDL_DEBUG_HEADER_NAME)
+endif()
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
     ./
     ./
@@ -24,9 +46,10 @@ INCLUDE_DIRECTORIES(
 )
 )
 
 
 link_directories(
 link_directories(
-    ./
+    ${CMAKE_HOME_DIRECTORY}/lib
 )
 )
 
 
+set( CMAKE_MODULE_PATH  ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake )
 SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
 SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
@@ -40,18 +63,38 @@ if( WIN32 AND NOT CYGWIN )
   endif()
   endif()
 elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
 elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
   # Update if necessary
   # Update if necessary
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++0x")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS}")
 elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
 elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS} -Wwrite-strings")
+endif()
+
+if (COVERALLS)
+    include(Coveralls)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
 endif()
 endif()
 
 
+# Include the doc component.
+FIND_PACKAGE( doxygen )
+IF ( DOXYGEN_FOUND )
+    CONFIGURE_FILE( doc/openddlparser_doc.in doc/doxygenfile @ONLY )
+    ADD_CUSTOM_TARGET( doc ALL ${DOXYGEN_EXECUTABLE} doc/doxygenfile
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        COMMENT "Generating API documentation with Doxygen" VERBATIM )
+ENDIF ( DOXYGEN_FOUND )
+
 SET ( openddl_parser_src
 SET ( openddl_parser_src
+    code/OpenDDLCommon.cpp
+    code/OpenDDLExport.cpp
     code/OpenDDLParser.cpp
     code/OpenDDLParser.cpp
+    code/OpenDDLStream.cpp
     code/DDLNode.cpp
     code/DDLNode.cpp
     code/Value.cpp
     code/Value.cpp
+    include/openddlparser/OpenDDLCommon.h
+    include/openddlparser/OpenDDLExport.h
     include/openddlparser/OpenDDLParser.h
     include/openddlparser/OpenDDLParser.h
     include/openddlparser/OpenDDLParserUtils.h
     include/openddlparser/OpenDDLParserUtils.h
-    include/openddlparser/OpenDDLCommon.h
+    include/openddlparser/OpenDDLStream.h
     include/openddlparser/DDLNode.h
     include/openddlparser/DDLNode.h
     include/openddlparser/Value.h
     include/openddlparser/Value.h
     README.md
     README.md
@@ -59,6 +102,69 @@ SET ( openddl_parser_src
  
  
 SOURCE_GROUP( code            FILES ${openddl_parser_src} )
 SOURCE_GROUP( code            FILES ${openddl_parser_src} )
 
 
-ADD_LIBRARY( openddl_parser SHARED
-    ${openddl_parser_src}
+if ( DDL_STATIC_LIBRARY )
+	ADD_LIBRARY( openddl_parser STATIC
+		${openddl_parser_src}
+	)
+else()
+	ADD_LIBRARY( openddl_parser SHARED
+		${openddl_parser_src}
+	)
+endif()
+
+SET ( GTEST_PATH contrib/gtest-1.7.0 )
+
+SET ( gtest_src
+    ${GTEST_PATH}/src/gtest-death-test.cc
+    ${GTEST_PATH}/src/gtest-filepath.cc
+    ${GTEST_PATH}/src/gtest-internal-inl.h
+    ${GTEST_PATH}/src/gtest-port.cc
+    ${GTEST_PATH}/src/gtest-printers.cc
+    ${GTEST_PATH}/src/gtest-test-part.cc
+    ${GTEST_PATH}/src/gtest-typed-test.cc
+    ${GTEST_PATH}/src/gtest.cc
+    ${GTEST_PATH}/src/gtest_main.cc
+)
+
+SET( openddl_parser_unittest_src  
+    test/UnitTestCommon.h
+    test/DDLNodeTest.cpp
+    test/OpenDDLCommonTest.cpp
+    test/OpenDDLExportTest.cpp
+    test/OpenDDLParserTest.cpp
+    test/OpenDDLParserUtilsTest.cpp
+    test/OpenDDLStreamTest.cpp
+    test/OpenDDLIntegrationTest.cpp
+    test/ValueTest.cpp
+    test/OpenDDLDefectsTest.cpp
+)
+
+SOURCE_GROUP( code  FILES ${openddl_parser_unittest_src} )
+SOURCE_GROUP( gtest FILES ${gtest_src} )
+
+ADD_EXECUTABLE( openddl_parser_unittest 
+    ${gtest_src}
+    ${openddl_parser_unittest_src}
+)
+
+target_link_libraries( openddl_parser_unittest openddl_parser ${CMAKE_THREAD_LIBS_INIT} )
+
+SET( openddl_parser_demo_src  
+    demo/main.cpp 
 )
 )
+
+if (COVERALLS)
+    set(COVERAGE_SRCS     ${gtest_src} ${openddl_parser_unittest_src} )
+
+    # Create the coveralls target.
+    coveralls_setup(
+        "${COVERAGE_SRCS}" # The source files.
+        ON                 # If we should upload.
+        "${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path.
+endif()
+
+ADD_EXECUTABLE( openddl_parser_demo
+    ${openddl_parser_demo_src}
+) 
+
+target_link_libraries( openddl_parser_demo openddl_parser )

+ 3 - 0
contrib/openddlparser/CREDITS

@@ -12,5 +12,8 @@ Improvements value interface, serveral bugfixes.
 - Henry Read ( henrya2 ):
 - Henry Read ( henrya2 ):
 Static build option, Interface improvements
 Static build option, Interface improvements
 
 
+- (wise86-android)
+fix several mem-leaks
+
 - Paul Holland ( pkholland ):
 - Paul Holland ( pkholland ):
 Bugfixes.
 Bugfixes.

+ 2 - 2
contrib/openddlparser/README.md

@@ -11,7 +11,7 @@ Current coverity check status:
   <img alt="Coverity Scan Build Status"
   <img alt="Coverity Scan Build Status"
        src="https://scan.coverity.com/projects/5606/badge.svg"/>
        src="https://scan.coverity.com/projects/5606/badge.svg"/>
 </a>
 </a>
-
+Current test coverage:[![Coverage Status](https://coveralls.io/repos/github/kimkulling/openddl-parser/badge.svg?branch=master)](https://coveralls.io/github/kimkulling/openddl-parser?branch=cpp_coveralls)
 Get the source code
 Get the source code
 ===================
 ===================
 You can get the code from our git repository, which is located at GitHub. You can clone the repository with the following command:
 You can get the code from our git repository, which is located at GitHub. You can clone the repository with the following command:
@@ -25,7 +25,7 @@ After installing it you can open a console and enter:
 
 
 > cmake CMakeLists.txt
 > cmake CMakeLists.txt
 
 
-This command will generate a build environment for your installed build enrironment ( for Visual-Studio-users the project files will be generated, for gcc-users the makefiles will be generated ).
+This command will generate a build environment for your preferred build tool ( for Visual-Studio-users the project files will be generated, for gcc-users the makefiles will be generated ).
 When using an IDE open the IDE and run the build. When using GNU-make type in your console:
 When using an IDE open the IDE and run the build. When using GNU-make type in your console:
 
 
 > make
 > make

+ 14 - 6
contrib/openddlparser/code/DDLNode.cpp

@@ -68,8 +68,8 @@ DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx,
 }
 }
 
 
 DDLNode::~DDLNode() {
 DDLNode::~DDLNode() {
-    releaseDataType<Property>( m_properties );
-    releaseDataType<Value>( m_value );
+    delete m_properties;
+    delete m_value;
     releaseReferencedNames( m_references );
     releaseReferencedNames( m_references );
 
 
     delete m_dtArrayList;
     delete m_dtArrayList;
@@ -77,6 +77,9 @@ DDLNode::~DDLNode() {
     if( s_allocatedNodes[ m_idx ] == this ) {
     if( s_allocatedNodes[ m_idx ] == this ) {
         s_allocatedNodes[ m_idx ] = ddl_nullptr;
         s_allocatedNodes[ m_idx ] = ddl_nullptr;
     }
     }
+    for ( size_t i = 0; i<m_children.size(); i++ ){
+        delete m_children[ i ];
+    }
 }
 }
 
 
 void DDLNode::attachParent( DDLNode *parent ) {
 void DDLNode::attachParent( DDLNode *parent ) {
@@ -91,9 +94,8 @@ void DDLNode::attachParent( DDLNode *parent ) {
 }
 }
 
 
 void DDLNode::detachParent() {
 void DDLNode::detachParent() {
-    if( m_parent ) {
-        std::vector<DDLNode*>::iterator it;
-        it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this );
+    if( ddl_nullptr != m_parent ) {
+        DDLNodeIt it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this );
         if( m_parent->m_children.end() != it ) {
         if( m_parent->m_children.end() != it ) {
             m_parent->m_children.erase( it );
             m_parent->m_children.erase( it );
         }
         }
@@ -126,6 +128,8 @@ const std::string &DDLNode::getName() const {
 }
 }
 
 
 void DDLNode::setProperties( Property *prop ) {
 void DDLNode::setProperties( Property *prop ) {
+    if(m_properties!=ddl_nullptr)
+        delete m_properties;
     m_properties = prop;
     m_properties = prop;
 }
 }
 
 
@@ -187,6 +191,10 @@ Reference *DDLNode::getReferences() const {
     return m_references;
     return m_references;
 }
 }
 
 
+void DDLNode::dump(IOStreamBase &stream) {
+    // Todo!    
+}
+
 DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) {
 DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) {
     const size_t idx( s_allocatedNodes.size() );
     const size_t idx( s_allocatedNodes.size() );
     DDLNode *node = new DDLNode( type, name, idx, parent );
     DDLNode *node = new DDLNode( type, name, idx, parent );
@@ -197,7 +205,7 @@ DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLN
 
 
 void DDLNode::releaseNodes() {
 void DDLNode::releaseNodes() {
     if( s_allocatedNodes.size() > 0 ) {
     if( s_allocatedNodes.size() > 0 ) {
-        for( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
+        for( DDLNodeIt it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
             if( *it ) {
             if( *it ) {
                 delete *it;
                 delete *it;
             }
             }

+ 35 - 9
contrib/openddlparser/code/OpenDDLCommon.cpp

@@ -22,6 +22,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 -----------------------------------------------------------------------------------------------*/
 #include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/DDLNode.h>
 #include <openddlparser/DDLNode.h>
+#include <openddlparser/Value.h>
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
@@ -84,7 +85,14 @@ Name::~Name() {
     m_id = ddl_nullptr;
     m_id = ddl_nullptr;
 }
 }
 
 
-Reference::Reference()
+Name::Name( const Name &name ){
+    m_type=name.m_type;
+    m_id=new Text(name.m_id->m_buffer,name.m_id->m_len);
+}
+
+
+
+    Reference::Reference()
 : m_numRefs( 0 )
 : m_numRefs( 0 )
 , m_referencedName( ddl_nullptr ) {
 , m_referencedName( ddl_nullptr ) {
     // empty
     // empty
@@ -96,8 +104,16 @@ Reference::Reference( size_t numrefs, Name **names )
     if ( numrefs > 0 ) {
     if ( numrefs > 0 ) {
         m_referencedName = new Name *[ numrefs ];
         m_referencedName = new Name *[ numrefs ];
         for ( size_t i = 0; i < numrefs; i++ ) {
         for ( size_t i = 0; i < numrefs; i++ ) {
-            Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id );
-            m_referencedName[ i ] = name;
+            m_referencedName[ i ] = names[i];
+        }
+    }
+}
+Reference::Reference(const Reference &ref) {
+    m_numRefs=ref.m_numRefs;
+    if(m_numRefs!=0){
+        m_referencedName = new Name*[m_numRefs];
+        for ( size_t i = 0; i < m_numRefs; i++ ) {
+            m_referencedName[i] = new Name(*ref.m_referencedName[i]);
         }
         }
     }
     }
 }
 }
@@ -107,6 +123,7 @@ Reference::~Reference() {
         delete m_referencedName[ i ];
         delete m_referencedName[ i ];
     }
     }
     m_numRefs = 0;
     m_numRefs = 0;
+    delete [] m_referencedName;
     m_referencedName = ddl_nullptr;
     m_referencedName = ddl_nullptr;
 }
 }
 
 
@@ -135,21 +152,30 @@ Property::Property( Text *id )
 }
 }
 
 
 Property::~Property() {
 Property::~Property() {
-    m_key = ddl_nullptr;
-    m_value = ddl_nullptr;
-    m_ref = ddl_nullptr;;
-    m_next = ddl_nullptr;;
+    delete m_key;
+    if(m_value!=ddl_nullptr)
+        delete m_value;
+    if(m_ref!=ddl_nullptr)
+        delete(m_ref);
+    if(m_next!=ddl_nullptr)
+        delete m_next;
 }
 }
 
 
 DataArrayList::DataArrayList()
 DataArrayList::DataArrayList()
 : m_numItems( 0 )
 : m_numItems( 0 )
 , m_dataList( ddl_nullptr )
 , m_dataList( ddl_nullptr )
-, m_next( ddl_nullptr ) {
+, m_next( ddl_nullptr )
+, m_refs(ddl_nullptr)
+, m_numRefs(0){
     // empty
     // empty
 }
 }
 
 
 DataArrayList::~DataArrayList() {
 DataArrayList::~DataArrayList() {
-    // empty
+    delete m_dataList;
+    if(m_next!=ddl_nullptr)
+        delete m_next;
+    if(m_refs!=ddl_nullptr)
+        delete m_refs;
 }
 }
 
 
 size_t DataArrayList::size() {
 size_t DataArrayList::size() {

+ 1 - 55
contrib/openddlparser/code/OpenDDLExport.cpp

@@ -29,60 +29,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
-StreamFormatterBase::StreamFormatterBase() {
-
-}
-
-StreamFormatterBase::~StreamFormatterBase() {
-
-}
-
-std::string StreamFormatterBase::format( const std::string &statement ) {
-    std::string tmp( statement );
-    return tmp;
-}
-
-IOStreamBase::IOStreamBase( StreamFormatterBase *formatter )
-: m_formatter( formatter )
-, m_file( ddl_nullptr ) {
-    if (ddl_nullptr == m_formatter) {
-        m_formatter = new StreamFormatterBase;
-    }
-}
-
-IOStreamBase::~IOStreamBase() {
-    delete m_formatter;
-    m_formatter = ddl_nullptr;
-}
-
-bool IOStreamBase::open( const std::string &name ) {
-    m_file = ::fopen( name.c_str(), "a" );
-    if (m_file == ddl_nullptr) {
-        return false;
-    }
-    
-    return true;
-}
-
-bool IOStreamBase::close() {
-    if (ddl_nullptr == m_file) {
-        return false;
-    }
-
-    ::fclose( m_file );
-    m_file = ddl_nullptr;
-
-    return true;
-}
-
-size_t IOStreamBase::write( const std::string &statement ) {
-    if (ddl_nullptr == m_file) {
-        return 0;
-    }
-    std::string formatStatement = m_formatter->format( statement );
-    return ::fwrite( formatStatement.c_str(), sizeof( char ), formatStatement.size(), m_file );
-}
-
 struct DDLNodeIterator {
 struct DDLNodeIterator {
     const DDLNode::DllNodeList &m_childs;
     const DDLNode::DllNodeList &m_childs;
     size_t m_idx;
     size_t m_idx;
@@ -280,7 +226,7 @@ bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std:
         statement += "[";
         statement += "[";
         char buffer[ 256 ];
         char buffer[ 256 ];
         ::memset( buffer, '\0', 256 * sizeof( char ) );
         ::memset( buffer, '\0', 256 * sizeof( char ) );
-        sprintf( buffer, "%d", int(numItems) );
+        sprintf( buffer, "%d", static_cast<int>( numItems ) );
         statement += buffer;
         statement += buffer;
         statement += "]";
         statement += "]";
     }
     }

+ 80 - 65
contrib/openddlparser/code/OpenDDLParser.cpp

@@ -36,7 +36,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
-static const char *Version = "0.3.0";
+static const char *Version = "0.4.0";
 
 
 namespace Grammar {
 namespace Grammar {
     static const char *OpenBracketToken   = "{";
     static const char *OpenBracketToken   = "{";
@@ -49,7 +49,7 @@ namespace Grammar {
     static const char *BoolFalse          = "false";
     static const char *BoolFalse          = "false";
     static const char *CommaSeparator     = ",";
     static const char *CommaSeparator     = ",";
 
 
-    static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
+    static const char *PrimitiveTypeToken[ Value::ddl_types_max ] = {
         "bool",
         "bool",
         "int8",
         "int8",
         "int16",
         "int16",
@@ -74,8 +74,8 @@ const char *getTypeToken( Value::ValueType  type ) {
 static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) {
 static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) {
     std::stringstream stream;
     std::stringstream stream;
     stream << "Invalid token \"" << *in << "\"" << " expected \"" << exp << "\"" << std::endl;
     stream << "Invalid token \"" << *in << "\"" << " expected \"" << exp << "\"" << std::endl;
-    std::string full(in);
-    std::string part(full.substr(0,50));
+    std::string full( in );
+    std::string part( full.substr( 0, 50 ) );
     stream << part;
     stream << part;
     callback( ddl_error_msg, stream.str() );
     callback( ddl_error_msg, stream.str() );
 }
 }
@@ -85,6 +85,7 @@ static bool isIntegerType( Value::ValueType integerType ) {
             integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
             integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
         return false;
         return false;
     }
     }
+    
     return true;
     return true;
 }
 }
 
 
@@ -105,7 +106,7 @@ static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) {
     const std::string type( id->m_buffer );
     const std::string type( id->m_buffer );
     DDLNode *parent( parser->top() );
     DDLNode *parent( parser->top() );
     DDLNode *node = DDLNode::create( type, "", parent );
     DDLNode *node = DDLNode::create( type, "", parent );
-
+    
     return node;
     return node;
 }
 }
 
 
@@ -193,10 +194,11 @@ size_t OpenDDLParser::getBufferSize() const {
 void OpenDDLParser::clear() {
 void OpenDDLParser::clear() {
     m_buffer.resize( 0 );
     m_buffer.resize( 0 );
     if( ddl_nullptr != m_context ) {
     if( ddl_nullptr != m_context ) {
-        m_context->m_root = ddl_nullptr;
+        delete m_context;
+        m_context=ddl_nullptr;
     }
     }
 
 
-    DDLNode::releaseNodes();
+//    DDLNode::releaseNodes();
 }
 }
 
 
 bool OpenDDLParser::parse() {
 bool OpenDDLParser::parse() {
@@ -212,11 +214,11 @@ bool OpenDDLParser::parse() {
 
 
     // do the main parsing
     // do the main parsing
     char *current( &m_buffer[ 0 ] );
     char *current( &m_buffer[ 0 ] );
-    char *end( &m_buffer[ m_buffer.size() - 1 ] + 1 );
+    char *end( &m_buffer[m_buffer.size() - 1 ] + 1 );
     size_t pos( current - &m_buffer[ 0 ] );
     size_t pos( current - &m_buffer[ 0 ] );
     while( pos < m_buffer.size() ) {
     while( pos < m_buffer.size() ) {
         current = parseNextNode( current, end );
         current = parseNextNode( current, end );
-        if(current==ddl_nullptr) {
+        if ( current == ddl_nullptr ) {
             return false;
             return false;
         }
         }
         pos = current - &m_buffer[ 0 ];
         pos = current - &m_buffer[ 0 ];
@@ -245,7 +247,7 @@ static void dumpId( Identifier *id ) {
     if( ddl_nullptr != id ) {
     if( ddl_nullptr != id ) {
         if ( ddl_nullptr != id->m_text.m_buffer ) {
         if ( ddl_nullptr != id->m_text.m_buffer ) {
             std::cout << id->m_text.m_buffer << std::endl;
             std::cout << id->m_text.m_buffer << std::endl;
-	}
+	    }
     }
     }
 }
 }
 #endif
 #endif
@@ -271,14 +273,17 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
         } else {
         } else {
             std::cerr << "nullptr returned by creating DDLNode." << std::endl;
             std::cerr << "nullptr returned by creating DDLNode." << std::endl;
         }
         }
+        delete id;
 
 
 		Name *name(ddl_nullptr);
 		Name *name(ddl_nullptr);
 		in = OpenDDLParser::parseName(in, end, &name);
 		in = OpenDDLParser::parseName(in, end, &name);
         if( ddl_nullptr != name && ddl_nullptr != node ) {
         if( ddl_nullptr != name && ddl_nullptr != node ) {
             const std::string nodeName( name->m_id->m_buffer );
             const std::string nodeName( name->m_id->m_buffer );
             node->setName( nodeName );
             node->setName( nodeName );
+            delete name;
         }
         }
 
 
+
 		Property *first(ddl_nullptr);
 		Property *first(ddl_nullptr);
 		in = lookForNextToken(in, end);
 		in = lookForNextToken(in, end);
 		if (*in == Grammar::OpenPropertyToken[0]) {
 		if (*in == Grammar::OpenPropertyToken[0]) {
@@ -303,7 +308,7 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
 					prev = prop;
 					prev = prop;
 				}
 				}
 			}
 			}
-			in++;
+			++in;
 		}
 		}
 
 
 		// set the properties
 		// set the properties
@@ -322,17 +327,17 @@ char *OpenDDLParser::parseStructure( char *in, char *end ) {
 
 
     bool error( false );
     bool error( false );
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
-    if( *in == '{' ) {
+    if( *in == *Grammar::OpenBracketToken) {
         // loop over all children ( data and nodes )
         // loop over all children ( data and nodes )
         do {
         do {
             in = parseStructureBody( in, end, error );
             in = parseStructureBody( in, end, error );
             if(in == ddl_nullptr){
             if(in == ddl_nullptr){
                 return ddl_nullptr;
                 return ddl_nullptr;
             }
             }
-        } while ( *in != '}' );
-        in++;
+        } while ( *in != *Grammar::CloseBracketToken);
+        ++in;
     } else {
     } else {
-        in++;
+        ++in;
         logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
         logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
         error = true;
         error = true;
         return ddl_nullptr;
         return ddl_nullptr;
@@ -373,7 +378,7 @@ static void setNodeDataArrayList( DDLNode *currentNode, DataArrayList *dtArrayLi
 
 
 char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
 char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
     if( !isNumeric( *in ) && !isCharacter( *in ) ) {
     if( !isNumeric( *in ) && !isCharacter( *in ) ) {
-        in++;
+        ++in;
     }
     }
 
 
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
@@ -431,7 +436,6 @@ DDLNode *OpenDDLParser::popNode() {
 
 
     DDLNode *topNode( top() );
     DDLNode *topNode( top() );
     m_stack.pop_back();
     m_stack.pop_back();
-
     return topNode;
     return topNode;
 }
 }
 
 
@@ -467,7 +471,14 @@ void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) {
     for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
     for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
         char *c( &buffer[readIdx] );
         char *c( &buffer[readIdx] );
         // check for a comment
         // check for a comment
-        if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
+        if (isCommentOpenTag(c, end)) {
+            ++readIdx;
+            while (!isCommentCloseTag(&buffer[readIdx], end)) {
+                ++readIdx;
+            }
+            ++readIdx;
+            ++readIdx;
+        } else if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
             newBuffer.push_back( buffer[ readIdx ] );
             newBuffer.push_back( buffer[ readIdx ] );
         } else {
         } else {
             if( isComment<char>( c, end ) ) {
             if( isComment<char>( c, end ) ) {
@@ -529,14 +540,17 @@ char *OpenDDLParser::parseIdentifier( char *in, char *end, Text **id ) {
     // get size of id
     // get size of id
     size_t idLen( 0 );
     size_t idLen( 0 );
     char *start( in );
     char *start( in );
-    while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != Grammar::OpenPropertyToken[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] && *in != '$' ) {
+    while( !isSeparator( *in ) && 
+            !isNewLine( *in ) && ( in != end ) && 
+            *in != Grammar::OpenPropertyToken[ 0 ] &&
+            *in != Grammar::ClosePropertyToken[ 0 ] && 
+            *in != '$' ) {
         ++in;
         ++in;
         ++idLen;
         ++idLen;
     }
     }
 
 
     const size_t len( idLen );
     const size_t len( idLen );
-    Text *newId = new Text( start, len );
-    *id = newId;
+    *id = new Text( start, len );
 
 
     return in;
     return in;
 }
 }
@@ -552,7 +566,7 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy
     for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
     for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
         prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] );
         prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] );
         if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) {
         if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) {
-            type = ( Value::ValueType ) i;
+            type = static_cast<Value::ValueType>( i );
             break;
             break;
         }
         }
     }
     }
@@ -567,14 +581,14 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy
     bool ok( true );
     bool ok( true );
     if( *in == Grammar::OpenArrayToken[ 0 ] ) {
     if( *in == Grammar::OpenArrayToken[ 0 ] ) {
         ok = false;
         ok = false;
-        in++;
+        ++in;
         char *start( in );
         char *start( in );
         while ( in != end ) {
         while ( in != end ) {
-            in++;
+            ++in;
             if( *in == Grammar::CloseArrayToken[ 0 ] ) {
             if( *in == Grammar::CloseArrayToken[ 0 ] ) {
                 len = ::atoi( start );
                 len = ::atoi( start );
                 ok = true;
                 ok = true;
-                in++;
+                ++in;
                 break;
                 break;
             }
             }
         }
         }
@@ -623,10 +637,10 @@ char *OpenDDLParser::parseBooleanLiteral( char *in, char *end, Value **boolean )
     char *start( in );
     char *start( in );
     size_t len( 0 );
     size_t len( 0 );
     while( !isSeparator( *in ) && in != end ) {
     while( !isSeparator( *in ) && in != end ) {
-        in++;
-        len++;
+        ++in;
+        ++len;
     }
     }
-    len++;
+    ++len;
     int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) );
     int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) );
     if( 0 != res ) {
     if( 0 != res ) {
         res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) );
         res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) );
@@ -657,7 +671,7 @@ char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer,
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
     char *start( in );
     char *start( in );
     while( !isSeparator( *in ) && in != end ) {
     while( !isSeparator( *in ) && in != end ) {
-        in++;
+        ++in;
     }
     }
 
 
     if( isNumeric( *start ) ) {
     if( isNumeric( *start ) ) {
@@ -671,29 +685,29 @@ char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer,
         *integer = ValueAllocator::allocPrimData( integerType );
         *integer = ValueAllocator::allocPrimData( integerType );
         switch( integerType ) {
         switch( integerType ) {
             case Value::ddl_int8:
             case Value::ddl_int8:
-                    ( *integer )->setInt8( (int8) value );
-                    break;
+                ( *integer )->setInt8( (int8) value );
+                break;
             case Value::ddl_int16:
             case Value::ddl_int16:
-                    ( *integer )->setInt16( ( int16 ) value );
-                    break;
+                ( *integer )->setInt16( ( int16 ) value );
+                break;
             case Value::ddl_int32:
             case Value::ddl_int32:
-                    ( *integer )->setInt32( ( int32 ) value );
-                    break;
+                ( *integer )->setInt32( ( int32 ) value );
+                break;
             case Value::ddl_int64:
             case Value::ddl_int64:
-                    ( *integer )->setInt64( ( int64 ) value );
-                    break;
+                ( *integer )->setInt64( ( int64 ) value );
+                break;
             case Value::ddl_unsigned_int8:
             case Value::ddl_unsigned_int8:
-                    ( *integer )->setUnsignedInt8( (uint8) uvalue );
-                    break;
+                ( *integer )->setUnsignedInt8( (uint8) uvalue );
+                break;
             case Value::ddl_unsigned_int16:
             case Value::ddl_unsigned_int16:
-                    ( *integer )->setUnsignedInt16( ( uint16 ) uvalue );
-                    break;
+                ( *integer )->setUnsignedInt16( ( uint16 ) uvalue );
+                break;
             case Value::ddl_unsigned_int32:
             case Value::ddl_unsigned_int32:
-                    ( *integer )->setUnsignedInt32( ( uint32 ) uvalue );
-                    break;
+                ( *integer )->setUnsignedInt32( ( uint32 ) uvalue );
+                break;
             case Value::ddl_unsigned_int64:
             case Value::ddl_unsigned_int64:
-                    ( *integer )->setUnsignedInt64( ( uint64 ) uvalue );
-                    break;
+                ( *integer )->setUnsignedInt64( ( uint64 ) uvalue );
+                break;
             default:
             default:
                 break;
                 break;
         }
         }
@@ -711,7 +725,7 @@ char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
     char *start( in );
     char *start( in );
     while( !isSeparator( *in ) && in != end ) {
     while( !isSeparator( *in ) && in != end ) {
-        in++;
+        ++in;
     }
     }
 
 
     // parse the float value
     // parse the float value
@@ -732,8 +746,7 @@ char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating
     }
     }
 
 
     if( ok ) {
     if( ok ) {
-        if(floatType == Value::ddl_double)
-        {
+        if ( floatType == Value::ddl_double ) {
             const double value( atof( start ) );
             const double value( atof( start ) );
             *floating = ValueAllocator::allocPrimData( Value::ddl_double );
             *floating = ValueAllocator::allocPrimData( Value::ddl_double );
             ( *floating )->setDouble( value );
             ( *floating )->setDouble( value );
@@ -757,17 +770,17 @@ char *OpenDDLParser::parseStringLiteral( char *in, char *end, Value **stringData
     size_t len( 0 );
     size_t len( 0 );
     char *start( in );
     char *start( in );
     if( *start == '\"' ) {
     if( *start == '\"' ) {
-        start++;
-        in++;
+        ++start;
+        ++in;
         while( *in != '\"' && in != end ) {
         while( *in != '\"' && in != end ) {
-            in++;
-            len++;
+            ++in;
+            ++len;
         }
         }
 
 
         *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len );
         *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len );
         ::strncpy( ( char* ) ( *stringData )->m_data, start, len );
         ::strncpy( ( char* ) ( *stringData )->m_data, start, len );
         ( *stringData )->m_data[len] = '\0';
         ( *stringData )->m_data[len] = '\0';
-        in++;
+        ++in;
     }
     }
 
 
     return in;
     return in;
@@ -791,12 +804,12 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
         return in;
         return in;
     }
     }
 
 
-    in++;
+    ++in;
     if( *in != 'x' && *in != 'X' ) {
     if( *in != 'x' && *in != 'X' ) {
         return in;
         return in;
     }
     }
 
 
-    in++;
+    ++in;
     bool ok( true );
     bool ok( true );
     char *start( in );
     char *start( in );
     int pos( 0 );
     int pos( 0 );
@@ -805,8 +818,8 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
             ok = false;
             ok = false;
             break;
             break;
         }
         }
-        pos++;
-        in++;
+        ++pos;
+        ++in;
     }
     }
 
 
     if( !ok ) {
     if( !ok ) {
@@ -816,9 +829,9 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
     int value( 0 );
     int value( 0 );
     while( pos > 0 ) {
     while( pos > 0 ) {
         int v = hex2Decimal( *start );
         int v = hex2Decimal( *start );
-        pos--;
+        --pos;
         value = ( value << 4 ) | v;
         value = ( value << 4 ) | v;
-        start++;
+        ++start;
     }
     }
 
 
     *data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 );
     *data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 );
@@ -841,7 +854,7 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
     if( ddl_nullptr != id ) {
     if( ddl_nullptr != id ) {
         in = lookForNextToken( in, end );
         in = lookForNextToken( in, end );
         if( *in == '=' ) {
         if( *in == '=' ) {
-            in++;
+            ++in;
             in = getNextToken( in, end );
             in = getNextToken( in, end );
             Value *primData( ddl_nullptr );
             Value *primData( ddl_nullptr );
             if( isInteger( in, end ) ) {
             if( isInteger( in, end ) ) {
@@ -862,6 +875,8 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
                     ( *prop )->m_ref = ref;
                     ( *prop )->m_ref = ref;
                 }
                 }
             }
             }
+        } else {
+            delete id;
         }
         }
     }
     }
 
 
@@ -878,7 +893,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
 
 
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
     if( *in == '{' ) {
     if( *in == '{' ) {
-        in++;
+        ++in;
         Value *current( ddl_nullptr ), *prev( ddl_nullptr );
         Value *current( ddl_nullptr ), *prev( ddl_nullptr );
         while( '}' != *in ) {
         while( '}' != *in ) {
             current = ddl_nullptr;
             current = ddl_nullptr;
@@ -934,7 +949,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
                     prev->setNext( current );
                     prev->setNext( current );
                     prev = current;
                     prev = current;
                 }
                 }
-                numValues++;
+                ++numValues;
             }
             }
 
 
             in = getNextSeparator( in, end );
             in = getNextSeparator( in, end );
@@ -942,7 +957,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
                 break;
                 break;
             }
             }
         }
         }
-        in++;
+        ++in;
     }
     }
 
 
     return in;
     return in;
@@ -972,7 +987,7 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType ty
 
 
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
     if( *in == Grammar::OpenBracketToken[ 0 ] ) {
     if( *in == Grammar::OpenBracketToken[ 0 ] ) {
-        in++;
+        ++in;
         Value *currentValue( ddl_nullptr );
         Value *currentValue( ddl_nullptr );
         Reference *refs( ddl_nullptr );
         Reference *refs( ddl_nullptr );
         DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr );
         DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr );
@@ -995,7 +1010,7 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType ty
             }
             }
         } while( Grammar::CommaSeparator[ 0 ] == *in && in != end );
         } while( Grammar::CommaSeparator[ 0 ] == *in && in != end );
         in = lookForNextToken( in, end );
         in = lookForNextToken( in, end );
-        in++;
+        ++in;
     }
     }
 
 
     return in;
     return in;

+ 96 - 0
contrib/openddlparser/code/OpenDDLStream.cpp

@@ -0,0 +1,96 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLStream.h>
+
+BEGIN_ODDLPARSER_NS
+
+StreamFormatterBase::StreamFormatterBase() {
+    // empty
+}
+
+StreamFormatterBase::~StreamFormatterBase() {
+    // empty
+}
+
+std::string StreamFormatterBase::format(const std::string &statement) {
+    std::string tmp(statement);
+    return tmp;
+}
+
+IOStreamBase::IOStreamBase(StreamFormatterBase *formatter)
+    : m_formatter(formatter)
+    , m_file(ddl_nullptr) {
+    if (ddl_nullptr == m_formatter) {
+        m_formatter = new StreamFormatterBase;
+    }
+}
+
+IOStreamBase::~IOStreamBase() {
+    delete m_formatter;
+    m_formatter = ddl_nullptr;
+}
+
+bool IOStreamBase::open(const std::string &name) {
+    m_file = ::fopen(name.c_str(), "a");
+    if (m_file == ddl_nullptr) {
+        return false;
+    }
+
+    return true;
+}
+
+bool IOStreamBase::close() {
+    if (ddl_nullptr == m_file) {
+        return false;
+    }
+
+    ::fclose(m_file);
+    m_file = ddl_nullptr;
+
+    return true;
+}
+
+bool IOStreamBase::isOpen() const {
+    return ( ddl_nullptr != m_file );
+}
+
+size_t IOStreamBase::read( size_t sizeToRead, std::string &statement ) {
+    if (ddl_nullptr == m_file) {
+        return 0;
+    }
+    
+    statement.resize(sizeToRead);
+    const size_t readBytes = ::fread( &statement[0], 1, sizeToRead, m_file );
+
+    return readBytes;
+}
+
+size_t IOStreamBase::write(const std::string &statement) {
+    if (ddl_nullptr == m_file) {
+        return 0;
+    }
+    std::string formatStatement = m_formatter->format(statement);
+    return ::fwrite(formatStatement.c_str(), sizeof(char), formatStatement.size(), m_file);
+}
+
+END_ODDLPARSER_NS

+ 17 - 18
contrib/openddlparser/code/Value.cpp

@@ -110,7 +110,17 @@ Value::Value( ValueType type )
 }
 }
 
 
 Value::~Value() {
 Value::~Value() {
-    // empty
+    if(m_data!=ddl_nullptr) {
+        if (m_type == ddl_ref ) {
+            Reference *tmp = (Reference *) m_data;
+            if (tmp != ddl_nullptr)
+                delete tmp;
+        }else
+            delete[] m_data;
+
+    }
+    if(m_next!=ddl_nullptr)
+        delete m_next;
 }
 }
 
 
 void Value::setBool( bool value ) {
 void Value::setBool( bool value ) {
@@ -273,13 +283,7 @@ void Value::setRef( Reference *ref ) {
                 delete [] m_data;
                 delete [] m_data;
             }
             }
 
 
-            m_data = new unsigned char[ sizeof( Reference ) ];
-            Reference *myRef = ( Reference * ) m_data;
-            myRef->m_numRefs = ref->m_numRefs;
-            myRef->m_referencedName =  new Name *[ myRef->m_numRefs ];
-            for ( size_t i = 0; i < myRef->m_numRefs; i++ ) {
-                myRef->m_referencedName[ i ] = new Name( ref->m_referencedName[ i ]->m_type, ref->m_referencedName[ i ]->m_id );
-            }
+            m_data = (unsigned char*) new Reference(*ref);
         }
         }
     }
     }
 }
 }
@@ -290,7 +294,7 @@ Reference *Value::getRef() const {
     return (Reference*) m_data;
     return (Reference*) m_data;
 }
 }
 
 
-void Value::dump() {
+void Value::dump( IOStreamBase &stream ) {
     switch( m_type ) {
     switch( m_type ) {
         case ddl_none:
         case ddl_none:
             std::cout << "None" << std::endl;
             std::cout << "None" << std::endl;
@@ -350,7 +354,7 @@ Value *Value::getNext() const {
     return m_next;
     return m_next;
 }
 }
 
 
-size_t Value::size(){
+size_t Value::size() const{
     size_t result=1;
     size_t result=1;
     Value *n=m_next;
     Value *n=m_next;
     while( n!=ddl_nullptr) {
     while( n!=ddl_nullptr) {
@@ -366,7 +370,6 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
     }
     }
 
 
     Value *data = new Value( type );
     Value *data = new Value( type );
-    data->m_type = type;
     switch( type ) {
     switch( type ) {
         case Value::ddl_bool:
         case Value::ddl_bool:
             data->m_size = sizeof( bool );
             data->m_size = sizeof( bool );
@@ -405,10 +408,10 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
             data->m_size = sizeof( double );
             data->m_size = sizeof( double );
             break;
             break;
         case Value::ddl_string:
         case Value::ddl_string:
-            data->m_size = sizeof( char );
+            data->m_size = sizeof( char )*(len+1);
             break;
             break;
         case Value::ddl_ref:
         case Value::ddl_ref:
-            data->m_size = sizeof( char );
+            data->m_size = 0;
             break;
             break;
         case Value::ddl_none:
         case Value::ddl_none:
         case Value::ddl_types_max:
         case Value::ddl_types_max:
@@ -417,12 +420,8 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
     }
     }
 
 
     if( data->m_size ) {
     if( data->m_size ) {
-        size_t len1( len );
-        if( Value::ddl_string == type ) {
-            len1++;
-        }
-        data->m_size *= len1;
         data->m_data = new unsigned char[ data->m_size ];
         data->m_data = new unsigned char[ data->m_size ];
+        ::memset(data->m_data,0,data->m_size);
     }
     }
 
 
     return data;
     return data;

+ 19 - 10
contrib/openddlparser/include/openddlparser/DDLNode.h

@@ -29,6 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
+// Forward declarations
+class IOStreamBase;
 class Value;
 class Value;
 class OpenDDLParser;
 class OpenDDLParser;
 
 
@@ -53,6 +55,9 @@ public:
     /// @brief  The child-node-list type.
     /// @brief  The child-node-list type.
     typedef std::vector<DDLNode*> DllNodeList;
     typedef std::vector<DDLNode*> DllNodeList;
 
 
+    /// @brief  The child-node-list iterator.
+    typedef std::vector<DDLNode*>::iterator DDLNodeIt;
+
 public:
 public:
     ///	@brief  The class destructor.
     ///	@brief  The class destructor.
     ~DDLNode();
     ~DDLNode();
@@ -81,7 +86,7 @@ public:
     const std::string &getType() const;
     const std::string &getType() const;
 
 
     /// Set the name of the DDLNode instance.
     /// Set the name of the DDLNode instance.
-    /// @param  type    [in] The name.
+    /// @param  name        [in] The name.
     void setName( const std::string &name );
     void setName( const std::string &name );
 
 
     /// @brief  Returns the name of the DDLNode instance.
     /// @brief  Returns the name of the DDLNode instance.
@@ -89,7 +94,7 @@ public:
     const std::string &getName() const;
     const std::string &getName() const;
 
 
     /// @brief  Set a new property set.
     /// @brief  Set a new property set.
-    ///	@param  prop    [in] The first element of the property set.
+    ///	@param  prop        [in] The first element of the property set.
     void setProperties( Property *prop );
     void setProperties( Property *prop );
 
 
     ///	@brief  Returns the first element of the assigned property set.
     ///	@brief  Returns the first element of the assigned property set.
@@ -97,7 +102,7 @@ public:
     Property *getProperties() const;
     Property *getProperties() const;
 
 
     ///	@brief  Looks for a given property.
     ///	@brief  Looks for a given property.
-    /// @param  name    [in] The name for the property to look for.
+    /// @param  name        [in] The name for the property to look for.
     /// @return true, if a corresponding property is assigned to the node, false if not.
     /// @return true, if a corresponding property is assigned to the node, false if not.
     bool hasProperty( const std::string &name );
     bool hasProperty( const std::string &name );
 
 
@@ -106,12 +111,12 @@ public:
     bool hasProperties() const;
     bool hasProperties() const;
 
 
     ///	@brief  Search for a given property and returns it. Will return ddl_nullptr if no property was found.
     ///	@brief  Search for a given property and returns it. Will return ddl_nullptr if no property was found.
-    /// @param  name    [in] The name for the property to look for.
+    /// @param  name        [in] The name for the property to look for.
     /// @return The property or ddl_nullptr if no property was found.
     /// @return The property or ddl_nullptr if no property was found.
     Property *findPropertyByName( const std::string &name );
     Property *findPropertyByName( const std::string &name );
     
     
     /// @brief  Set a new value set.
     /// @brief  Set a new value set.
-    /// @param  val     [in] The first value instance of the value set.
+    /// @param  val         [in] The first value instance of the value set.
     void setValue( Value *val );
     void setValue( Value *val );
 
 
     ///	@brief  Returns the first element of the assigned value set.
     ///	@brief  Returns the first element of the assigned value set.
@@ -119,7 +124,7 @@ public:
     Value *getValue() const;
     Value *getValue() const;
 
 
     /// @brief  Set a new DataArrayList.
     /// @brief  Set a new DataArrayList.
-    /// @param  val     [in] The DataArrayList instance.
+    /// @param  dtArrayList [in] The DataArrayList instance.
     void setDataArrayList( DataArrayList *dtArrayList );
     void setDataArrayList( DataArrayList *dtArrayList );
 
 
     ///	@brief  Returns the DataArrayList.
     ///	@brief  Returns the DataArrayList.
@@ -127,17 +132,21 @@ public:
     DataArrayList *getDataArrayList() const;
     DataArrayList *getDataArrayList() const;
 
 
     /// @brief  Set a new Reference set.
     /// @brief  Set a new Reference set.
-    /// @param  val     [in] The first value instance of the Reference set.
+    /// @param  refs        [in] The first value instance of the Reference set.
     void setReferences( Reference  *refs );
     void setReferences( Reference  *refs );
 
 
     ///	@brief  Returns the first element of the assigned Reference set.
     ///	@brief  Returns the first element of the assigned Reference set.
     ///	@return The first property of the assigned Reference set.
     ///	@return The first property of the assigned Reference set.
     Reference *getReferences() const;
     Reference *getReferences() const;
 
 
+    /// @brief  Will dump the node into the stream.
+    /// @param  stream      [in] The stream to write to.
+    void dump(IOStreamBase &stream);
+
     ///	@brief  The creation method.
     ///	@brief  The creation method.
-    /// @param  type    [in] The DDLNode type.
-    ///	@param  name    [in] The name for the new DDLNode instance.
-    /// @param  parent  [in] The parent node instance or ddl_nullptr if no parent node is there.
+    /// @param  type        [in] The DDLNode type.
+    ///	@param  name        [in] The name for the new DDLNode instance.
+    /// @param  parent      [in] The parent node instance or ddl_nullptr if no parent node is there.
     /// @return The new created node instance.
     /// @return The new created node instance.
     static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = ddl_nullptr );
     static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = ddl_nullptr );
 
 

+ 3 - 4
contrib/openddlparser/include/openddlparser/OpenDDLCommon.h

@@ -148,12 +148,12 @@ struct DLL_ODDLPARSER_EXPORT Name {
     ///	@param  type    [in] The name type.
     ///	@param  type    [in] The name type.
     ///	@param  id      [in] The id.
     ///	@param  id      [in] The id.
     Name( NameType type, Text *id );
     Name( NameType type, Text *id );
-
+    Name( const Name &name );
     ///	@brief  The destructor.
     ///	@brief  The destructor.
     ~Name();
     ~Name();
 
 
 private:
 private:
-    Name( const Name & ) ddl_no_copy;
+
     Name &operator = ( const Name& ) ddl_no_copy;
     Name &operator = ( const Name& ) ddl_no_copy;
 };
 };
 
 
@@ -164,7 +164,7 @@ struct DLL_ODDLPARSER_EXPORT Reference {
 
 
     ///	@brief  The default constructor.
     ///	@brief  The default constructor.
     Reference();
     Reference();
-
+    Reference( const Reference &ref );
     ///	@brief  The constructor with an array of ref names.
     ///	@brief  The constructor with an array of ref names.
     /// @param  numrefs     [in] The number of ref names.
     /// @param  numrefs     [in] The number of ref names.
     /// @param  names       [in] The ref names.
     /// @param  names       [in] The ref names.
@@ -178,7 +178,6 @@ struct DLL_ODDLPARSER_EXPORT Reference {
     size_t sizeInBytes();
     size_t sizeInBytes();
 
 
 private:
 private:
-    Reference( const Reference & ) ddl_no_copy;
     Reference &operator = ( const Reference & ) ddl_no_copy;
     Reference &operator = ( const Reference & ) ddl_no_copy;
 };
 };
 
 

+ 3 - 27
contrib/openddlparser/include/openddlparser/OpenDDLExport.h

@@ -23,37 +23,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 #pragma once
 
 
 #include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/OpenDDLStream.h>
 #include <openddlparser/Value.h>
 #include <openddlparser/Value.h>
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
-//-------------------------------------------------------------------------------------------------
-/// @ingroup    IOStreamBase
-///	@brief      This class represents the stream to write out.
-//-------------------------------------------------------------------------------------------------
-class DLL_ODDLPARSER_EXPORT StreamFormatterBase {
-public:
-    StreamFormatterBase();
-    virtual ~StreamFormatterBase();
-    virtual std::string format( const std::string &statement );
-};
-
-//-------------------------------------------------------------------------------------------------
-/// @ingroup    IOStreamBase
-///	@brief      This class represents the stream to write out.
-//-------------------------------------------------------------------------------------------------
-class DLL_ODDLPARSER_EXPORT IOStreamBase {
-public:
-    IOStreamBase( StreamFormatterBase *formatter = ddl_nullptr );
-    virtual ~IOStreamBase();
-    virtual bool open( const std::string &anme );
-    virtual bool close();
-    virtual size_t write( const std::string &statement );
-
-private:
-    StreamFormatterBase *m_formatter;
-    FILE *m_file;
-};
+// Forward declarations
+class IOStreamBase;
 
 
 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------
 ///
 ///

+ 11 - 1
contrib/openddlparser/include/openddlparser/OpenDDLParser.h

@@ -39,6 +39,16 @@ struct Identifier;
 struct Reference;
 struct Reference;
 struct Property;
 struct Property;
 
 
+template<class T>
+inline
+bool isEmbeddedCommentOpenTag( T *in, T *end ) {
+    if ( in == '/' && in+1 == '*' ) {
+        return true;
+    }
+
+    return false;
+}
+
 ///	@brief  Utility function to search for the next token or the end of the buffer.
 ///	@brief  Utility function to search for the next token or the end of the buffer.
 /// @param  in      [in] The start position in the buffer.
 /// @param  in      [in] The start position in the buffer.
 /// @param  end     [in] The end position in the buffer.
 /// @param  end     [in] The end position in the buffer.
@@ -47,7 +57,7 @@ struct Property;
 template<class T>
 template<class T>
 inline
 inline
 T *lookForNextToken( T *in, T *end ) {
 T *lookForNextToken( T *in, T *end ) {
-    while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
+    while( ( in != end ) && ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) ) {
         in++;
         in++;
     }
     }
     return in;
     return in;

+ 36 - 8
contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h

@@ -84,7 +84,7 @@ static const unsigned char chartype_table[ 256 ] = {
 template<class T>
 template<class T>
 inline
 inline
 bool isNumeric( const T in ) {
 bool isNumeric( const T in ) {
-	return ( chartype_table[ static_cast<int>( in ) ] == 1 );
+    return ( chartype_table[ static_cast<size_t>( in ) ] == 1 );
 }
 }
 
 
 template<class T>
 template<class T>
@@ -98,7 +98,7 @@ inline
 bool isInteger( T *in, T *end ) {
 bool isInteger( T *in, T *end ) {
     if( in != end ) {
     if( in != end ) {
         if( *in == '-' ) {
         if( *in == '-' ) {
-            in++;
+            ++in;
         }
         }
     }
     }
 
 
@@ -108,7 +108,7 @@ bool isInteger( T *in, T *end ) {
         if( !result ) {
         if( !result ) {
             break;
             break;
         }
         }
-        in++;
+        ++in;
     }
     }
 
 
     return result;
     return result;
@@ -119,7 +119,7 @@ inline
 bool isFloat( T *in, T *end ) {
 bool isFloat( T *in, T *end ) {
     if( in != end ) {
     if( in != end ) {
         if( *in == '-' ) {
         if( *in == '-' ) {
-            in++;
+            ++in;
         }
         }
     }
     }
 
 
@@ -134,12 +134,12 @@ bool isFloat( T *in, T *end ) {
         if( !result ) {
         if( !result ) {
             return false;
             return false;
         }
         }
-        in++;
+        ++in;
     }
     }
 
 
     // check for 1<.>0f
     // check for 1<.>0f
     if( *in == '.' ) {
     if( *in == '.' ) {
-        in++;
+        ++in;
     } else {
     } else {
         return false;
         return false;
     }
     }
@@ -150,7 +150,7 @@ bool isFloat( T *in, T *end ) {
         if( !result ) {
         if( !result ) {
             return false;
             return false;
         }
         }
-        in++;
+        ++in;
     }
     }
 
 
     return result;
     return result;
@@ -208,7 +208,7 @@ template<class T>
 inline
 inline
 static T *getNextSeparator( T *in, T *end ) {
 static T *getNextSeparator( T *in, T *end ) {
     while( !isSeparator( *in ) || in == end ) {
     while( !isSeparator( *in ) || in == end ) {
-        in++;
+        ++in;
     }
     }
     return in;
     return in;
 }
 }
@@ -250,5 +250,33 @@ bool isComment( T *in, T *end ) {
     return false;
     return false;
 }
 }
 
 
+template<class T>
+inline
+bool isCommentOpenTag(T *in, T *end ) {
+    if (*in == '/') {
+        if (in + 1 != end) {
+            if (*(in + 1) == '*') {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+template<class T>
+inline
+bool isCommentCloseTag(T *in, T *end) {
+    if (*in == '*') {
+        if (in + 1 != end) {
+            if (*(in + 1) == '/') {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
 END_ODDLPARSER_NS
 END_ODDLPARSER_NS
 
 

+ 89 - 0
contrib/openddlparser/include/openddlparser/OpenDDLStream.h

@@ -0,0 +1,89 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup    IOStreamBase
+///	@brief      This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT StreamFormatterBase {
+public:
+    /// @brief  The class constructor.
+    StreamFormatterBase();
+
+    /// @brief  The class destructor, virtual.
+    virtual ~StreamFormatterBase();
+
+    /// @brief  Will format the sring and return the new formatted result.
+    /// @param  statement   [in] The string to reformat.
+    /// @return The reformatted result.
+    virtual std::string format(const std::string &statement);
+};
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup    IOStreamBase
+///	@brief      This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT IOStreamBase {
+public:
+    /// @brief  The class constructor with the formatter.
+    /// @param  formatter   [in] The formatter to use.
+    explicit IOStreamBase(StreamFormatterBase *formatter = ddl_nullptr);
+
+    /// @brief  The class destructor, virtual.
+    virtual ~IOStreamBase();
+
+    /// @brief  Will open the stream.
+    /// @param  name        [in] The name for the stream.
+    /// @return true, if the stream was opened successfully, false if not.
+    virtual bool open(const std::string &name);
+
+    /// @brief  Will close the stream.
+    /// @return true, if the stream was closed successfully, false if not.
+    virtual bool close();
+
+    /// @brief  Returns true, if the stream is open.
+    /// @return true, if the stream is open, false if not.
+    virtual bool isOpen() const;
+
+    /// @brief  Will read a string from the stream.
+    /// @param  sizeToRead  [in] The size to read in bytes.
+    /// @param  statement   [out] The read statements.
+    /// @return The bytes read from the stream.
+    virtual size_t read( size_t sizeToRead, std::string &statement );
+
+    /// @brief  Will write a string into the stream.
+    /// @param  statement  [in] The string to write.
+    /// @return The bytes written into the stream.
+    virtual size_t write(const std::string &statement);
+
+private:
+    StreamFormatterBase *m_formatter;
+    FILE *m_file;
+};
+
+END_ODDLPARSER_NS

+ 7 - 3
contrib/openddlparser/include/openddlparser/Value.h

@@ -28,8 +28,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
+// Forward declarations
 struct ValueAllocator;
 struct ValueAllocator;
 
 
+class IOStreamBase;
+
 ///------------------------------------------------------------------------------------------------
 ///------------------------------------------------------------------------------------------------
 ///	@brief  This class implements a value.
 ///	@brief  This class implements a value.
 ///
 ///
@@ -213,7 +216,7 @@ public:
     double getDouble() const;
     double getDouble() const;
 
 
     ///	@brief  Assigns a std::string to the value.
     ///	@brief  Assigns a std::string to the value.
-    /// @param  value       [in] The value.
+    /// @param  str         [in] The value.
     void setString( const std::string &str );
     void setString( const std::string &str );
 
 
     ///	@brief  Returns the std::string value.
     ///	@brief  Returns the std::string value.
@@ -229,7 +232,8 @@ public:
     Reference *getRef() const;
     Reference *getRef() const;
 
 
     ///	@brief  Dumps the value.
     ///	@brief  Dumps the value.
-    void dump();
+    /// @param  stream  [in] The stream to write in.
+    void dump( IOStreamBase &stream );
 
 
     ///	@brief  Assigns the next value.
     ///	@brief  Assigns the next value.
     ///	@param  next        [n] The next value.
     ///	@param  next        [n] The next value.
@@ -241,7 +245,7 @@ public:
 
 
     /// @brief  Gets the length of the array.
     /// @brief  Gets the length of the array.
     /// @return The number of items in the array.
     /// @return The number of items in the array.
-    size_t size();
+    size_t size() const;
 
 
     ValueType m_type;
     ValueType m_type;
     size_t m_size;
     size_t m_size;

+ 0 - 2
code/SceneCombiner.h → include/assimp/SceneCombiner.h

@@ -143,7 +143,6 @@ struct NodeAttachmentInfo
  */
  */
 #define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10
 #define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10
 
 
-
 typedef std::pair<aiBone*,unsigned int> BoneSrcIndex;
 typedef std::pair<aiBone*,unsigned int> BoneSrcIndex;
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -153,7 +152,6 @@ struct BoneWithHash : public std::pair<uint32_t,aiString*>  {
     std::vector<BoneSrcIndex> pSrcBones;
     std::vector<BoneSrcIndex> pSrcBones;
 };
 };
 
 
-
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @brief Utility for SceneCombiner
 /** @brief Utility for SceneCombiner
  */
  */

+ 10 - 3
include/assimp/config.h.in

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -632,8 +632,15 @@ enum aiComponent
 #define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \
 #define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \
     "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
     "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
 
 
-
-
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will search for embedded loaded textures, where no embedded texture data is provided.
+*
+* The default value is false (0)
+* Property type: bool
+*/
+#define AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES \
+	"IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES"
+	
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @brief  Set the vertex animation keyframe to be imported
 /** @brief  Set the vertex animation keyframe to be imported
  *
  *

+ 16 - 4
include/assimp/material.inl

@@ -48,6 +48,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_MATERIAL_INL_INC
 #ifndef AI_MATERIAL_INL_INC
 #define AI_MATERIAL_INL_INC
 #define AI_MATERIAL_INL_INC
 
 
+// ---------------------------------------------------------------------------
+inline aiPropertyTypeInfo ai_real_to_property_type_info(float)
+{
+	return aiPTI_Float;
+}
+
+inline aiPropertyTypeInfo ai_real_to_property_type_info(double)
+{
+	return aiPTI_Double;
+}
+// ---------------------------------------------------------------------------
+
 //! @cond never
 //! @cond never
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -223,7 +235,7 @@ inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput,
 {
 {
     return AddBinaryProperty((const void*)pInput,
     return AddBinaryProperty((const void*)pInput,
         pNumValues * sizeof(aiUVTransform),
         pNumValues * sizeof(aiUVTransform),
-        pKey,type,index,aiPTI_Float); //TODO could be Double ...
+        pKey,type,index,ai_real_to_property_type_info(pInput->mRotation));
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -235,7 +247,7 @@ inline aiReturn aiMaterial::AddProperty(const aiColor4D* pInput,
 {
 {
     return AddBinaryProperty((const void*)pInput,
     return AddBinaryProperty((const void*)pInput,
         pNumValues * sizeof(aiColor4D),
         pNumValues * sizeof(aiColor4D),
-        pKey,type,index,aiPTI_Float); //TODO could be Double ...
+        pKey,type,index,ai_real_to_property_type_info(pInput->a));
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -247,7 +259,7 @@ inline aiReturn aiMaterial::AddProperty(const aiColor3D* pInput,
 {
 {
     return AddBinaryProperty((const void*)pInput,
     return AddBinaryProperty((const void*)pInput,
         pNumValues * sizeof(aiColor3D),
         pNumValues * sizeof(aiColor3D),
-        pKey,type,index,aiPTI_Float); //TODO could be Double ...
+        pKey,type,index,ai_real_to_property_type_info(pInput->b));
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -259,7 +271,7 @@ inline aiReturn aiMaterial::AddProperty(const aiVector3D* pInput,
 {
 {
     return AddBinaryProperty((const void*)pInput,
     return AddBinaryProperty((const void*)pInput,
         pNumValues * sizeof(aiVector3D),
         pNumValues * sizeof(aiVector3D),
-        pKey,type,index,aiPTI_Float); //TODO could be Double ...
+        pKey,type,index,ai_real_to_property_type_info(pInput->x));
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------

+ 94 - 94
port/PyAssimp/README.md

@@ -1,94 +1,94 @@
-PyAssimp Readme
-===============
-
-A simple Python wrapper for Assimp using `ctypes` to access the library.
-Requires Python >= 2.6.
-
-Python 3 support is mostly here, but not well tested.
-
-Note that pyassimp is not complete. Many ASSIMP features are missing.
-
-USAGE
------
-
-### Complete example: 3D viewer
-
-`pyassimp` comes with a simple 3D viewer that shows how to load and display a 3D
-model using a shader-based OpenGL pipeline.
-
-![Screenshot](3d_viewer_screenshot.png)
-
-To use it, from within `/port/PyAssimp`:
-
-```
-$ cd scripts
-$ python ./3D-viewer <path to your model>
-```
-
-You can use this code as starting point in your applications.
-
-### Writing your own code
-
-To get started with `pyassimp`, examine the simpler `sample.py` script in `scripts/`,
-which illustrates the basic usage. All Assimp data structures are wrapped using
-`ctypes`. All the data+length fields in Assimp's data structures (such as
-`aiMesh::mNumVertices`, `aiMesh::mVertices`) are replaced by simple python
-lists, so you can call `len()` on them to get their respective size and access
-members using `[]`.
-
-For example, to load a file named `hello.3ds` and print the first
-vertex of the first mesh, you would do (proper error handling
-substituted by assertions ...):
-
-```python
-
-from pyassimp import *
-scene = load('hello.3ds')
-
-assert len(scene.meshes)
-mesh = scene.meshes[0]
-
-assert len(mesh.vertices)
-print(mesh.vertices[0])
-
-# don't forget this one, or you will leak!
-release(scene)
-
-```
-
-Another example to list the 'top nodes' in a
-scene:
-
-```python
-
-from pyassimp import *
-scene = load('hello.3ds')
-
-for c in scene.rootnode.children:
-    print(str(c))
-
-release(scene)
-
-```
-
-INSTALL
--------
-
-Install `pyassimp` by running:
-
-```
-$ python setup.py install
-```
-
-PyAssimp requires a assimp dynamic library (`DLL` on windows,
-`.so` on linux, `.dynlib` on macOS) in order to work. The default search directories 
-are:
-
-- the current directory
-- on linux additionally: `/usr/lib`, `/usr/local/lib`,
-  `/usr/lib/x86_64-linux-gnu`
-
-To build that library, refer to the Assimp master `INSTALL`
-instructions. To look in more places, edit `./pyassimp/helper.py`.
-There's an `additional_dirs` list waiting for your entries.
-
+PyAssimp Readme
+===============
+
+A simple Python wrapper for Assimp using `ctypes` to access the library.
+Requires Python >= 2.6.
+
+Python 3 support is mostly here, but not well tested.
+
+Note that pyassimp is not complete. Many ASSIMP features are missing.
+
+USAGE
+-----
+
+### Complete example: 3D viewer
+
+`pyassimp` comes with a simple 3D viewer that shows how to load and display a 3D
+model using a shader-based OpenGL pipeline.
+
+![Screenshot](3d_viewer_screenshot.png)
+
+To use it, from within `/port/PyAssimp`:
+
+```
+$ cd scripts
+$ python ./3D-viewer <path to your model>
+```
+
+You can use this code as starting point in your applications.
+
+### Writing your own code
+
+To get started with `pyassimp`, examine the simpler `sample.py` script in `scripts/`,
+which illustrates the basic usage. All Assimp data structures are wrapped using
+`ctypes`. All the data+length fields in Assimp's data structures (such as
+`aiMesh::mNumVertices`, `aiMesh::mVertices`) are replaced by simple python
+lists, so you can call `len()` on them to get their respective size and access
+members using `[]`.
+
+For example, to load a file named `hello.3ds` and print the first
+vertex of the first mesh, you would do (proper error handling
+substituted by assertions ...):
+
+```python
+
+from pyassimp import *
+scene = load('hello.3ds')
+
+assert len(scene.meshes)
+mesh = scene.meshes[0]
+
+assert len(mesh.vertices)
+print(mesh.vertices[0])
+
+# don't forget this one, or you will leak!
+release(scene)
+
+```
+
+Another example to list the 'top nodes' in a
+scene:
+
+```python
+
+from pyassimp import *
+scene = load('hello.3ds')
+
+for c in scene.rootnode.children:
+    print(str(c))
+
+release(scene)
+
+```
+
+INSTALL
+-------
+
+Install `pyassimp` by running:
+
+```
+$ python setup.py install
+```
+
+PyAssimp requires a assimp dynamic library (`DLL` on windows,
+`.so` on linux, `.dynlib` on macOS) in order to work. The default search directories 
+are:
+
+- the current directory
+- on linux additionally: `/usr/lib`, `/usr/local/lib`,
+  `/usr/lib/x86_64-linux-gnu`
+
+To build that library, refer to the Assimp master `INSTALL`
+instructions. To look in more places, edit `./pyassimp/helper.py`.
+There's an `additional_dirs` list waiting for your entries.
+

+ 1 - 1
port/PyAssimp/scripts/3d_viewer.py

@@ -679,7 +679,7 @@ class PyAssimp3DViewer:
         logger.info("Loading model:" + path + "...")
         logger.info("Loading model:" + path + "...")
 
 
         if postprocess:
         if postprocess:
-            self.scene = pyassimp.load(path, postprocess)
+            self.scene = pyassimp.load(path, processing=postprocess)
         else:
         else:
             self.scene = pyassimp.load(path)
             self.scene = pyassimp.load(path)
         logger.info("Done.")
         logger.info("Done.")

+ 1 - 1
port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py

@@ -98,7 +98,7 @@ class GLRenderer():
         logger.info("Loading model:" + path + "...")
         logger.info("Loading model:" + path + "...")
 
 
         if postprocess:
         if postprocess:
-            self.scene = pyassimp.load(path, postprocess)
+            self.scene = pyassimp.load(path, processing=postprocess)
         else:
         else:
             self.scene = pyassimp.load(path)
             self.scene = pyassimp.load(path)
         logger.info("Done.")
         logger.info("Done.")

+ 1 - 1
port/PyAssimp/scripts/sample.py

@@ -20,7 +20,7 @@ def recur_node(node,level = 0):
 
 
 def main(filename=None):
 def main(filename=None):
 
 
-    scene = pyassimp.load(filename, pyassimp.postprocess.aiProcess_Triangulate)
+    scene = pyassimp.load(filename, processing=pyassimp.postprocess.aiProcess_Triangulate)
     
     
     #the model we load
     #the model we load
     print("MODEL:" + filename)
     print("MODEL:" + filename)

+ 2 - 2
port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake

@@ -7,8 +7,8 @@ SET (CMAKE_SYSTEM_PROCESSOR "arm64")
 SET (SDKVER     "7.1")
 SET (SDKVER     "7.1")
 SET (DEVROOT    "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain")
 SET (DEVROOT    "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain")
 SET (SDKROOT    "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${SDKVER}.sdk")
 SET (SDKROOT    "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${SDKVER}.sdk")
-SET (CC         "${DEVROOT}/usr/bin/llvm-gcc")
-SET (CXX        "${DEVROOT}/usr/bin/llvm-g++")
+SET (CC "${DEVROOT}/usr/bin/clang")
+SET (CXX "${DEVROOT}/usr/bin/clang++")
 
 
 CMAKE_FORCE_C_COMPILER          (${CC} LLVM)
 CMAKE_FORCE_C_COMPILER          (${CC} LLVM)
 CMAKE_FORCE_CXX_COMPILER        (${CXX} LLVM)
 CMAKE_FORCE_CXX_COMPILER        (${CXX} LLVM)

+ 4 - 0
test/unit/ut3DSImportExport.cpp

@@ -53,7 +53,11 @@ public:
     virtual bool importerTest() {
     virtual bool importerTest() {
         Assimp::Importer importer;
         Assimp::Importer importer;
         const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/3DS/fels.3ds", 0 );
         const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/3DS/fels.3ds", 0 );
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
         return nullptr != scene;
         return nullptr != scene;
+#else
+        return nullptr == scene;
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
     }
     }
 };
 };
 
 

+ 4 - 0
test/unit/utASEImportExport.cpp

@@ -53,7 +53,11 @@ public:
     virtual bool importerTest() {
     virtual bool importerTest() {
         Assimp::Importer importer;
         Assimp::Importer importer;
         const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/ASE/ThreeCubesGreen.ASE", 0 );
         const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/ASE/ThreeCubesGreen.ASE", 0 );
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
         return nullptr != scene;
         return nullptr != scene;
+#else 
+        return nullptr == scene;
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
     }
     }
 };
 };
 
 

+ 1 - 0
test/unit/utBatchLoader.cpp

@@ -66,6 +66,7 @@ TEST_F( BatchLoaderTest, createTest ) {
     } catch ( ... ) {
     } catch ( ... ) {
         ok = false;
         ok = false;
     }
     }
+    EXPECT_TRUE( ok );
 }
 }
 
 
 TEST_F( BatchLoaderTest, validateAccessTest ) {
 TEST_F( BatchLoaderTest, validateAccessTest ) {

+ 1 - 1
test/unit/utObjTools.cpp

@@ -109,8 +109,8 @@ TEST_F( utObjTools, countComponents_TwoLines_Success ) {
     buffer.resize( data.size() );
     buffer.resize( data.size() );
     ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
     ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
     test_parser.setBuffer( buffer );
     test_parser.setBuffer( buffer );
-    static const size_t Size = 4096UL;
 
 
     size_t numComps = test_parser.testGetNumComponentsInDataDefinition();
     size_t numComps = test_parser.testGetNumComponentsInDataDefinition();
     EXPECT_EQ( 3U, numComps );
     EXPECT_EQ( 3U, numComps );
 }
 }
+

+ 2 - 4
test/unit/utglTFImportExport.cpp

@@ -50,10 +50,8 @@ class utglTFImportExport : public AbstractImportExportBase {
 public:
 public:
     virtual bool importerTest() {
     virtual bool importerTest() {
         Assimp::Importer importer;
         Assimp::Importer importer;
-        const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glFT/TwoBoxes/TwoBoxes.gltf", 0 );
-        //return nullptr != scene;
-
-        return true;
+        const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF/TwoBoxes/TwoBoxes.gltf", 0 );
+        return nullptr != scene;
     }
     }
 };
 };