Forráskód Böngészése

Merge branch 'master' into fix/3365

Kim Kulling 4 éve
szülő
commit
3fd95aff4e
40 módosított fájl, 3561 hozzáadás és 3171 törlés
  1. 0 1
      .github/FUNDING.yml
  2. 1 5
      CMakeLists.txt
  3. 1 1
      cmake-modules/FindRT.cmake
  4. 0 1
      code/AssetLib/Blender/BlenderDNA.cpp
  5. 6 7
      code/AssetLib/Blender/BlenderDNA.h
  6. 5 38
      code/AssetLib/Blender/BlenderLoader.h
  7. 5 2
      code/AssetLib/Blender/BlenderScene.h
  8. 1 1
      code/AssetLib/Collada/ColladaExporter.cpp
  9. 1 2
      code/AssetLib/Collada/ColladaHelper.cpp
  10. 109 119
      code/AssetLib/Collada/ColladaHelper.h
  11. 8 9
      code/AssetLib/Collada/ColladaLoader.cpp
  12. 161 192
      code/AssetLib/Collada/ColladaParser.cpp
  13. 12 22
      code/AssetLib/Collada/ColladaParser.h
  14. 5 0
      code/AssetLib/FBX/FBXImporter.cpp
  15. 1 1
      code/AssetLib/FBX/FBXMaterial.cpp
  16. 408 413
      code/AssetLib/OpenGEX/OpenGEXImporter.cpp
  17. 5 5
      code/AssetLib/glTF/glTFAsset.inl
  18. 25 1
      code/AssetLib/glTF2/glTF2Asset.inl
  19. 1122 1123
      code/AssetLib/glTF2/glTF2Importer.cpp
  20. 2 4
      code/Common/Version.cpp
  21. 0 1
      contrib/CMakeLists.txt
  22. 12 12
      contrib/openddlparser/CMakeLists.txt
  23. 77 67
      contrib/openddlparser/code/DDLNode.cpp
  24. 66 78
      contrib/openddlparser/code/OpenDDLCommon.cpp
  25. 159 181
      contrib/openddlparser/code/OpenDDLExport.cpp
  26. 344 337
      contrib/openddlparser/code/OpenDDLParser.cpp
  27. 15 15
      contrib/openddlparser/code/OpenDDLStream.cpp
  28. 194 196
      contrib/openddlparser/code/Value.cpp
  29. 19 19
      contrib/openddlparser/include/openddlparser/DDLNode.h
  30. 74 75
      contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
  31. 13 13
      contrib/openddlparser/include/openddlparser/OpenDDLExport.h
  32. 51 55
      contrib/openddlparser/include/openddlparser/OpenDDLParser.h
  33. 346 104
      contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
  34. 4 4
      contrib/openddlparser/include/openddlparser/OpenDDLStream.h
  35. 226 0
      contrib/openddlparser/include/openddlparser/TPoolAllocator.h
  36. 2 2
      contrib/openddlparser/include/openddlparser/Value.h
  37. 50 51
      include/assimp/StringUtils.h
  38. 11 1
      include/assimp/XmlParser.h
  39. 19 12
      include/assimp/fast_atof.h
  40. 1 1
      test/unit/utOpenGEXImportExport.cpp

+ 0 - 1
.github/FUNDING.yml

@@ -1,3 +1,2 @@
 patreon: assimp
 custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4
-open_collective: assimp

+ 1 - 5
CMakeLists.txt

@@ -353,7 +353,7 @@ ELSE()
 ENDIF()
 
 # Only generate this target if no higher-level project already has
-IF (NOT TARGET uninstall)
+IF (NOT TARGET uninstall AND ASSIMP_INSTALL)
   # add make uninstall capability
   CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
   ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
@@ -563,10 +563,6 @@ ELSE ()
   ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
 ENDIF ()
 
-#IF(NOT ASSIMP_HUNTER_ENABLED)
-  ADD_SUBDIRECTORY(contrib)
-#ENDIF()
-
 ADD_SUBDIRECTORY( code/ )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
   # The viewer for windows only

+ 1 - 1
cmake-modules/FindRT.cmake

@@ -16,5 +16,5 @@ set(RT_LIBRARIES ${RT_LIBRARY})
 # handle the QUIETLY and REQUIRED arguments and set
 # RT_FOUND to TRUE if all listed variables are TRUE
 include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(rt DEFAULT_MSG RT_LIBRARY)
+find_package_handle_standard_args(RT DEFAULT_MSG RT_LIBRARY)
 mark_as_advanced(RT_LIBRARY)

+ 0 - 1
code/AssetLib/Blender/BlenderDNA.cpp

@@ -139,7 +139,6 @@ void DNAParser::Parse() {
         dna.structures.push_back(Structure());
         Structure &s = dna.structures.back();
         s.name = types[n].name;
-        //s.index = dna.structures.size()-1;
 
         n = stream.GetI2();
         s.fields.reserve(n);

+ 6 - 7
code/AssetLib/Blender/BlenderDNA.h

@@ -83,10 +83,9 @@ class ObjectCache;
  *  ancestry. */
 // -------------------------------------------------------------------------------
 struct Error : DeadlyImportError {
-    template<typename... T>
-    explicit Error(T&&... args)
-        : DeadlyImportError(args...)
-    {
+    template <typename... T>
+    explicit Error(T &&...args) :
+            DeadlyImportError(args...) {
     }
 };
 
@@ -187,7 +186,7 @@ struct Field {
 };
 
 // -------------------------------------------------------------------------------
-/** Range of possible behaviours for fields absend in the input file. Some are
+/** Range of possible behaviors for fields absence in the input file. Some are
  *  mission critical so we need them, while others can silently be default
  *  initialized and no animations are harmed. */
 // -------------------------------------------------------------------------------
@@ -395,7 +394,7 @@ private:
 
 // --------------------------------------------------------
 template <>
-struct Structure ::_defaultInitializer<ErrorPolicy_Warn> {
+struct Structure::_defaultInitializer<ErrorPolicy_Warn> {
 
     template <typename T>
     void operator()(T &out, const char *reason = "<add reason>") {
@@ -407,7 +406,7 @@ struct Structure ::_defaultInitializer<ErrorPolicy_Warn> {
 };
 
 template <>
-struct Structure ::_defaultInitializer<ErrorPolicy_Fail> {
+struct Structure::_defaultInitializer<ErrorPolicy_Fail> {
 
     template <typename T>
     void operator()(T & /*out*/, const char * = "") {

+ 5 - 38
code/AssetLib/Blender/BlenderLoader.h

@@ -106,51 +106,18 @@ class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter
 public:
     BlenderImporter();
     ~BlenderImporter();
-
-public:
-
-    // --------------------
-    bool CanRead( const std::string& pFile,
-        IOSystem* pIOHandler,
-        bool checkSig
-    ) const;
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
 
 protected:
-
-    // --------------------
     const aiImporterDesc* GetInfo () const;
-
-    // --------------------
     void GetExtensionList(std::set<std::string>& app);
-
-    // --------------------
     void SetupProperties(const Importer* pImp);
-
-    // --------------------
-    void InternReadFile( const std::string& pFile,
-        aiScene* pScene,
-        IOSystem* pIOHandler
-    );
-
-    // --------------------
-    void ParseBlendFile(Blender::FileDatabase& out,
-        std::shared_ptr<IOStream> stream
-    );
-
-    // --------------------
-    void ExtractScene(Blender::Scene& out,
-        const Blender::FileDatabase& file
-    );
-
-    // --------------------
-    void ConvertBlendFile(aiScene* out,
-        const Blender::Scene& in,
-        const Blender::FileDatabase& file
-    );
+    void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+    void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream);
+    void ExtractScene(Blender::Scene& out, const Blender::FileDatabase& file);
+    void ConvertBlendFile(aiScene* out, const Blender::Scene& in, const Blender::FileDatabase& file);
 
 private:
-
-    // --------------------
     aiNode* ConvertNode(const Blender::Scene& in,
         const Blender::Object* obj,
         Blender::ConversionData& conv_info,

+ 5 - 2
code/AssetLib/Blender/BlenderScene.h

@@ -155,7 +155,7 @@ struct World : ElemBase {
 // -------------------------------------------------------------------------------
 struct MVert : ElemBase {
     float co[3] FAIL;
-    float no[3] FAIL; // readed as short and divided through / 32767.f
+    float no[3] FAIL; // read as short and divided through / 32767.f
     char flag;
     int mat_nr WARN;
     int bweight;
@@ -228,7 +228,10 @@ struct TFace : ElemBase {
 // -------------------------------------------------------------------------------
 struct MTFace : ElemBase {
     MTFace() :
-            flag(0), mode(0), tile(0), unwrap(0) {
+            flag(0),
+            mode(0),
+            tile(0),
+            unwrap(0) {
     }
 
     float uv[4][2] FAIL;

+ 1 - 1
code/AssetLib/Collada/ColladaExporter.cpp

@@ -573,7 +573,7 @@ bool ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial &
             index_str = index_str.substr(1, std::string::npos);
 
             try {
-                index = (unsigned int)strtoul10_64(index_str.c_str());
+                index = (unsigned int)strtoul10_64<DeadlyExportError>(index_str.c_str());
             } catch (std::exception &error) {
                 throw DeadlyExportError(error.what());
             }

+ 1 - 2
code/AssetLib/Collada/ColladaHelper.cpp

@@ -1,5 +1,3 @@
-/** Helper structures for the Collada loader */
-
 /*
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
@@ -40,6 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ----------------------------------------------------------------------
 */
+/** Helper structures for the Collada loader */
 
 #include "ColladaHelper.h"
 

+ 109 - 119
code/AssetLib/Collada/ColladaHelper.h

@@ -1,12 +1,9 @@
-/** Helper structures for the Collada loader */
-
 /*
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -42,12 +39,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
+/** Helper structures for the Collada loader */
+
 #ifndef AI_COLLADAHELPER_H_INC
 #define AI_COLLADAHELPER_H_INC
 
 #include <assimp/light.h>
 #include <assimp/material.h>
 #include <assimp/mesh.h>
+
 #include <stdint.h>
 #include <map>
 #include <set>
@@ -58,14 +58,14 @@ struct aiMaterial;
 namespace Assimp {
 namespace Collada {
 
-/** Collada file versions which evolved during the years ... */
+/// Collada file versions which evolved during the years ...
 enum FormatVersion {
     FV_1_5_n,
     FV_1_4_n,
     FV_1_3_n
 };
 
-/** Transformation types that can be applied to a node */
+/// Transformation types that can be applied to a node
 enum TransformType {
     TF_LOOKAT,
     TF_ROTATE,
@@ -75,7 +75,7 @@ enum TransformType {
     TF_MATRIX
 };
 
-/** Different types of input data to a vertex or face */
+/// Different types of input data to a vertex or face
 enum InputType {
     IT_Invalid,
     IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
@@ -87,38 +87,39 @@ enum InputType {
     IT_Bitangent
 };
 
-/** Supported controller types */
+/// Supported controller types
 enum ControllerType {
     Skin,
     Morph
 };
 
-/** Supported morph methods */
+/// Supported morph methods
 enum MorphMethod {
     Normalized,
     Relative
 };
 
-/** Common metadata keys as <Collada, Assimp> */
-typedef std::pair<std::string, std::string> MetaKeyPair;
-typedef std::vector<MetaKeyPair> MetaKeyPairVector;
+/// Common metadata keys as <Collada, Assimp>
+using MetaKeyPair = std::pair<std::string, std::string>;
+using MetaKeyPairVector = std::vector<MetaKeyPair>;
 
-// Collada as lower_case (native)
+/// Collada as lower_case (native)
 const MetaKeyPairVector &GetColladaAssimpMetaKeys();
+
 // Collada as CamelCase (used by Assimp for consistency)
 const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase();
 
-/** Convert underscore_separated to CamelCase "authoring_tool" becomes "AuthoringTool" */
+/// Convert underscore_separated to CamelCase "authoring_tool" becomes "AuthoringTool"
 void ToCamelCase(std::string &text);
 
-/** Contains all data for one of the different transformation types */
+/// Contains all data for one of the different transformation types
 struct Transform {
     std::string mID; ///< SID of the transform step, by which anim channels address their target node
     TransformType mType;
     ai_real f[16]; ///< Interpretation of data depends on the type of the transformation
 };
 
-/** A collada camera. */
+/// A collada camera.
 struct Camera {
     Camera() :
             mOrtho(false),
@@ -128,22 +129,22 @@ struct Camera {
             mZNear(0.1f),
             mZFar(1000.f) {}
 
-    // Name of camera
+    /// Name of camera
     std::string mName;
 
-    // True if it is an orthografic camera
+    /// True if it is an orthographic camera
     bool mOrtho;
 
-    //! Horizontal field of view in degrees
+    /// Horizontal field of view in degrees
     ai_real mHorFov;
 
-    //! Vertical field of view in degrees
+    /// Vertical field of view in degrees
     ai_real mVerFov;
 
-    //! Screen aspect
+    /// Screen aspect
     ai_real mAspect;
 
-    //! Near& far z
+    /// Near& far z
     ai_real mZNear, mZFar;
 };
 
@@ -162,27 +163,27 @@ struct Light {
             mOuterAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET),
             mIntensity(1.f) {}
 
-    //! Type of the light source aiLightSourceType + ambient
+    /// Type of the light source aiLightSourceType + ambient
     unsigned int mType;
 
-    //! Color of the light
+    /// Color of the light
     aiColor3D mColor;
 
-    //! Light attenuation
+    /// Light attenuation
     ai_real mAttConstant, mAttLinear, mAttQuadratic;
 
-    //! Spot light falloff
+    /// Spot light falloff
     ai_real mFalloffAngle;
     ai_real mFalloffExponent;
 
     // -----------------------------------------------------
     // FCOLLADA extension from here
 
-    //! ... related stuff from maja and max extensions
+    /// ... related stuff from maja and max extensions
     ai_real mPenumbraAngle;
     ai_real mOuterAngle;
 
-    //! Common light intensity
+    /// Common light intensity
     ai_real mIntensity;
 };
 
@@ -192,30 +193,29 @@ struct InputSemanticMapEntry {
             mSet(0),
             mType(IT_Invalid) {}
 
-    //! Index of set, optional
+    /// Index of set, optional
     unsigned int mSet;
 
-    //! Type of referenced vertex input
+    /// Type of referenced vertex input
     InputType mType;
 };
 
-/** Table to map from effect to vertex input semantics */
+/// Table to map from effect to vertex input semantics
 struct SemanticMappingTable {
-    //! Name of material
+    /// Name of material
     std::string mMatName;
 
-    //! List of semantic map commands, grouped by effect semantic name
+    /// List of semantic map commands, grouped by effect semantic name
     std::map<std::string, InputSemanticMapEntry> mMap;
 
-    //! For std::find
+    /// For std::find
     bool operator==(const std::string &s) const {
         return s == mMatName;
     }
 };
 
-/** A reference to a mesh inside a node, including materials assigned to the various subgroups.
- * The ID refers to either a mesh or a controller which specifies the mesh
- */
+/// A reference to a mesh inside a node, including materials assigned to the various subgroups.
+/// The ID refers to either a mesh or a controller which specifies the mesh
 struct MeshInstance {
     ///< ID of the mesh or controller to be instanced
     std::string mMeshOrController;
@@ -224,25 +224,25 @@ struct MeshInstance {
     std::map<std::string, SemanticMappingTable> mMaterials;
 };
 
-/** A reference to a camera inside a node*/
+/// A reference to a camera inside a node
 struct CameraInstance {
     ///< ID of the camera
     std::string mCamera;
 };
 
-/** A reference to a light inside a node*/
+/// A reference to a light inside a node
 struct LightInstance {
     ///< ID of the camera
     std::string mLight;
 };
 
-/** A reference to a node inside a node*/
+/// A reference to a node inside a node
 struct NodeInstance {
     ///< ID of the node
     std::string mNode;
 };
 
-/** A node in a scene hierarchy */
+/// A node in a scene hierarchy
 struct Node {
     std::string mName;
     std::string mID;
@@ -250,52 +250,53 @@ struct Node {
     Node *mParent;
     std::vector<Node *> mChildren;
 
-    /** Operations in order to calculate the resulting transformation to parent. */
+    /// Operations in order to calculate the resulting transformation to parent.
     std::vector<Transform> mTransforms;
 
-    /** Meshes at this node */
+    /// Meshes at this node
     std::vector<MeshInstance> mMeshes;
 
-    /** Lights at this node */
+    /// Lights at this node
     std::vector<LightInstance> mLights;
 
-    /** Cameras at this node */
+    /// Cameras at this node
     std::vector<CameraInstance> mCameras;
 
-    /** Node instances at this node */
+    /// Node instances at this node
     std::vector<NodeInstance> mNodeInstances;
 
-    /** Root-nodes: Name of primary camera, if any */
+    /// Root-nodes: Name of primary camera, if any
     std::string mPrimaryCamera;
 
-    //! Constructor. Begin with a zero parent
+    /// Constructor. Begin with a zero parent
     Node() :
             mParent(nullptr) {
         // empty
     }
 
-    //! Destructor: delete all children subsequently
+    /// Destructor: delete all children subsequently
     ~Node() {
-        for (std::vector<Node *>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
+        for (std::vector<Node *>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) {
             delete *it;
+        }
     }
 };
 
-/** Data source array: either floats or strings */
+/// Data source array: either floats or strings
 struct Data {
     bool mIsStringArray;
     std::vector<ai_real> mValues;
     std::vector<std::string> mStrings;
 };
 
-/** Accessor to a data array */
+/// Accessor to a data array
 struct Accessor {
     size_t mCount; // in number of objects
     size_t mSize; // size of an object, in elements (floats or strings, mostly 1)
     size_t mOffset; // in number of values
     size_t mStride; // Stride in number of values
     std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
-    size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on.
+    size_t mSubOffset[4]; // Sub-offset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on.
             // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
     std::string mSource; // URL of the source array
     mutable const Data *mData; // Pointer to the source array, if resolved. nullptr else
@@ -310,12 +311,12 @@ struct Accessor {
     }
 };
 
-/** A single face in a mesh */
+/// A single face in a mesh
 struct Face {
     std::vector<size_t> mIndices;
 };
 
-/** An input channel for mesh data, referring to a single accessor */
+/// An input channel for mesh data, referring to a single accessor
 struct InputChannel {
     InputType mType; // Type of the data
     size_t mIndex; // Optional index, if multiple sets of the same data type are given
@@ -331,18 +332,19 @@ struct InputChannel {
     }
 };
 
-/** Subset of a mesh with a certain material */
+/// Subset of a mesh with a certain material
 struct SubMesh {
     std::string mMaterial; ///< subgroup identifier
-    size_t mNumFaces; ///< number of faces in this submesh
+    size_t mNumFaces; ///< number of faces in this sub-mesh
 };
 
-/** Contains data for a single mesh */
+/// Contains data for a single mesh
 struct Mesh {
     Mesh(const std::string &id) :
             mId(id) {
-        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i)
+        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
             mNumUVComponents[i] = 2;
+        }
     }
 
     const std::string mId;
@@ -373,11 +375,11 @@ struct Mesh {
     // necessary for bone weight assignment
     std::vector<size_t> mFacePosIndices;
 
-    // Submeshes in this mesh, each with a given material
+    // Sub-meshes in this mesh, each with a given material
     std::vector<SubMesh> mSubMeshes;
 };
 
-/** Which type of primitives the ReadPrimitives() function is going to read */
+/// Which type of primitives the ReadPrimitives() function is going to read
 enum PrimitiveType {
     Prim_Invalid,
     Prim_Lines,
@@ -389,7 +391,7 @@ enum PrimitiveType {
     Prim_Polygon
 };
 
-/** A skeleton controller to deform a mesh with the use of joints */
+/// A skeleton controller to deform a mesh with the use of joints
 struct Controller {
     // controller type
     ControllerType mType;
@@ -424,25 +426,25 @@ struct Controller {
     std::string mMorphWeight;
 };
 
-/** A collada material. Pretty much the only member is a reference to an effect. */
+/// A collada material. Pretty much the only member is a reference to an effect.
 struct Material {
     std::string mName;
     std::string mEffect;
 };
 
-/** Type of the effect param */
+/// Type of the effect param
 enum ParamType {
     Param_Sampler,
     Param_Surface
 };
 
-/** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
+/// A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them
 struct EffectParam {
     ParamType mType;
     std::string mReference; // to which other thing the param is referring to.
 };
 
-/** Shading type supported by the standard effect spec of Collada */
+/// Shading type supported by the standard effect spec of Collada
 enum ShadeType {
     Shade_Invalid,
     Shade_Constant,
@@ -451,7 +453,7 @@ enum ShadeType {
     Shade_Blinn
 };
 
-/** Represents a texture sampler in collada */
+/// Represents a texture sampler in collada
 struct Sampler {
     Sampler() :
             mWrapU(true),
@@ -463,77 +465,66 @@ struct Sampler {
             mWeighting(1.f),
             mMixWithPrevious(1.f) {}
 
-    /** Name of image reference
-     */
+    /// Name of image reference
     std::string mName;
 
-    /** Wrap U?
-     */
+    /// Wrap U?
     bool mWrapU;
 
-    /** Wrap V?
-     */
+    /// Wrap V?
     bool mWrapV;
 
-    /** Mirror U?
-     */
+    /// Mirror U?
     bool mMirrorU;
 
-    /** Mirror V?
-     */
+    /// Mirror V?
     bool mMirrorV;
 
-    /** Blend mode
-     */
+    /// Blend mode
     aiTextureOp mOp;
 
-    /** UV transformation
-     */
+    /// UV transformation
     aiUVTransform mTransform;
 
-    /** Name of source UV channel
-     */
+    /// Name of source UV channel
     std::string mUVChannel;
 
-    /** Resolved UV channel index or UINT_MAX if not known
-     */
+    /// Resolved UV channel index or UINT_MAX if not known
     unsigned int mUVId;
 
     // OKINO/MAX3D extensions from here
     // -------------------------------------------------------
 
-    /** Weighting factor
-     */
+    /// Weighting factor
     ai_real mWeighting;
 
-    /** Mixing factor from OKINO
-     */
+    /// Mixing factor from OKINO
     ai_real mMixWithPrevious;
 };
 
-/** A collada effect. Can contain about anything according to the Collada spec,
-    but we limit our version to a reasonable subset. */
+/// A collada effect. Can contain about anything according to the Collada spec,
+/// but we limit our version to a reasonable subset.
 struct Effect {
-    // Shading mode
+    /// Shading mode
     ShadeType mShadeType;
 
-    // Colors
+    /// Colors
     aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
             mTransparent, mReflective;
 
-    // Textures
+    /// Textures
     Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
             mTexTransparent, mTexBump, mTexReflective;
 
-    // Scalar factory
+    /// Scalar factory
     ai_real mShininess, mRefractIndex, mReflectivity;
     ai_real mTransparency;
     bool mHasTransparency;
     bool mRGBTransparency;
     bool mInvertTransparency;
 
-    // local params referring to each other by their SID
-    typedef std::map<std::string, Collada::EffectParam> ParamLibrary;
+    /// local params referring to each other by their SID
+    using ParamLibrary = std::map<std::string, Collada::EffectParam>;
     ParamLibrary mParams;
 
     // MAX3D extensions
@@ -561,65 +552,64 @@ struct Effect {
     }
 };
 
-/** An image, meaning texture */
+/// An image, meaning texture
 struct Image {
     std::string mFileName;
 
-    /** Embedded image data */
+    /// Embedded image data
     std::vector<uint8_t> mImageData;
 
-    /** File format hint of embedded image data */
+    /// File format hint of embedded image data
     std::string mEmbeddedFormat;
 };
 
-/** An animation channel. */
+/// An animation channel.
 struct AnimationChannel {
-    /** URL of the data to animate. Could be about anything, but we support only the
-     * "NodeID/TransformID.SubElement" notation
-     */
+    /// URL of the data to animate. Could be about anything, but we support only the
+    /// "NodeID/TransformID.SubElement" notation
     std::string mTarget;
 
-    /** Source URL of the time values. Collada calls them "input". Meh. */
+    /// Source URL of the time values. Collada calls them "input". Meh.
     std::string mSourceTimes;
-    /** Source URL of the value values. Collada calls them "output". */
+    /// Source URL of the value values. Collada calls them "output".
     std::string mSourceValues;
-    /** Source URL of the IN_TANGENT semantic values. */
+    /// Source URL of the IN_TANGENT semantic values.
     std::string mInTanValues;
-    /** Source URL of the OUT_TANGENT semantic values. */
+    /// Source URL of the OUT_TANGENT semantic values.
     std::string mOutTanValues;
-    /** Source URL of the INTERPOLATION semantic values. */
+    /// Source URL of the INTERPOLATION semantic values.
     std::string mInterpolationValues;
 };
 
-/** An animation. Container for 0-x animation channels or 0-x animations */
+/// An animation. Container for 0-x animation channels or 0-x animations
 struct Animation {
-    /** Anim name */
+    /// Anim name
     std::string mName;
 
-    /** the animation channels, if any */
+    /// the animation channels, if any
     std::vector<AnimationChannel> mChannels;
 
-    /** the sub-animations, if any */
+    /// the sub-animations, if any
     std::vector<Animation *> mSubAnims;
 
-    /** Destructor */
+    /// Destructor
     ~Animation() {
-        for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
+        for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) {
             delete *it;
+        }
     }
 
-    /** Collect all channels in the animation hierarchy into a single channel list. */
+    /// Collect all channels in the animation hierarchy into a single channel list.
     void CollectChannelsRecursively(std::vector<AnimationChannel> &channels) {
         channels.insert(channels.end(), mChannels.begin(), mChannels.end());
 
         for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) {
             Animation *pAnim = (*it);
-
             pAnim->CollectChannelsRecursively(channels);
         }
     }
 
-    /** Combine all single-channel animations' channel into the same (parent) animation channel list. */
+    /// Combine all single-channel animations' channel into the same (parent) animation channel list.
     void CombineSingleChannelAnimations() {
         CombineSingleChannelAnimationsRecursively(this);
     }
@@ -658,9 +648,9 @@ struct Animation {
     }
 };
 
-/** Description of a collada animation channel which has been determined to affect the current node */
+/// Description of a collada animation channel which has been determined to affect the current node
 struct ChannelEntry {
-    const Collada::AnimationChannel *mChannel; ///> the source channel
+    const Collada::AnimationChannel *mChannel; ///< the source channel
     std::string mTargetId;
     std::string mTransformId; // the ID of the transformation step of the node which is influenced
     size_t mTransformIndex; // Index into the node's transform chain to apply the channel to

+ 8 - 9
code/AssetLib/Collada/ColladaLoader.cpp

@@ -55,12 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/fast_atof.h>
 #include <assimp/importerdesc.h>
 #include <assimp/scene.h>
-#include <math.h>
-#include <time.h>
-#include <algorithm>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/Importer.hpp>
-#include <memory>
+
 #include <numeric>
 
 namespace Assimp {
@@ -331,13 +328,15 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Col
 // Resolve UV channels
 void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler &sampler, const Collada::SemanticMappingTable &table) {
     std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
-    if (it != table.mMap.end()) {
-        if (it->second.mType != Collada::IT_Texcoord) {
-            ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
-        }
+    if (it == table.mMap.end()) {
+        return;
+    }
 
-        sampler.mUVId = it->second.mSet;
+    if (it->second.mType != Collada::IT_Texcoord) {
+        ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
     }
+
+    sampler.mUVId = it->second.mSet;
 }
 
 // ------------------------------------------------------------------------------------------------

+ 161 - 192
code/AssetLib/Collada/ColladaParser.cpp

@@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ColladaParser.h"
 #include <assimp/ParsingUtils.h>
 #include <assimp/StringUtils.h>
-#include <assimp/TinyFormatter.h>
 #include <assimp/ZipArchiveIOSystem.h>
 #include <assimp/commonMetaData.h>
 #include <assimp/fast_atof.h>
@@ -56,14 +55,47 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
 
-#include <stdarg.h>
-#include <memory>
-#include <sstream>
-
 using namespace Assimp;
 using namespace Assimp::Collada;
 using namespace Assimp::Formatter;
 
+static void ReportWarning(const char *msg, ...) {
+    ai_assert(nullptr != msg);
+
+    va_list args;
+    va_start(args, msg);
+
+    char szBuffer[3000];
+    const int iLen = vsprintf(szBuffer, msg, args);
+    ai_assert(iLen > 0);
+
+    va_end(args);
+    ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer, iLen));
+}
+
+static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) {
+    for (size_t i = 0; i < key_renaming.size(); ++i) {
+        if (key_renaming[i].first == collada_key) {
+            found_index = i;
+            return true;
+        }
+    }
+    found_index = std::numeric_limits<size_t>::max();
+
+    return false;
+}
+
+static void readUrlAttribute(XmlNode &node, std::string &url) {
+    url.clear();
+    if (!XmlParser::getStdStrAttribute(node, "url", url)) {
+        return;
+    }
+    if (url[0] != '#') {
+        throw DeadlyImportError("Unknown reference format");
+    }
+    url = url.c_str() + 1;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
@@ -256,35 +288,35 @@ void ColladaParser::ReadContents(XmlNode &node) {
 // ------------------------------------------------------------------------------------------------
 // Reads the structure of the file
 void ColladaParser::ReadStructure(XmlNode &node) {
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string name = std::string(currentNode.name());
-        ASSIMP_LOG_DEBUG("last name" + name);
-        if (name == "asset")
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = std::string(currentNode.name());
+        if (currentName == "asset") {
             ReadAssetInfo(currentNode);
-        else if (name == "library_animations")
+        } else if (currentName == "library_animations") {
             ReadAnimationLibrary(currentNode);
-        else if (name == "library_animation_clips")
+        } else if (currentName == "library_animation_clips") {
             ReadAnimationClipLibrary(currentNode);
-        else if (name == "library_controllers")
+        } else if (currentName == "library_controllers") {
             ReadControllerLibrary(currentNode);
-        else if (name == "library_images")
+        } else if (currentName == "library_images") {
             ReadImageLibrary(currentNode);
-        else if (name == "library_materials")
+        } else if (currentName == "library_materials") {
             ReadMaterialLibrary(currentNode);
-        else if (name == "library_effects")
+        } else if (currentName == "library_effects") {
             ReadEffectLibrary(currentNode);
-        else if (name == "library_geometries")
+        } else if (currentName == "library_geometries") {
             ReadGeometryLibrary(currentNode);
-        else if (name == "library_visual_scenes")
+        } else if (currentName == "library_visual_scenes") {
             ReadSceneLibrary(currentNode);
-        else if (name == "library_lights")
+        } else if (currentName == "library_lights") {
             ReadLightLibrary(currentNode);
-        else if (name == "library_cameras")
+        } else if (currentName == "library_cameras") {
             ReadCameraLibrary(currentNode);
-        else if (name == "library_nodes")
+        } else if (currentName == "library_nodes") {
             ReadSceneNode(currentNode, nullptr); /* some hacking to reuse this piece of code */
-        else if (name == "scene")
+        } else if (currentName == "scene") {
             ReadScene(currentNode);
+        }
     }
 
     PostProcessRootAnimations();
@@ -298,17 +330,16 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
         return;
     }
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string name = currentNode.name();
-        if (name == "unit") {
-            pugi::xml_attribute attr = currentNode.attribute("meter");
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
+        if (currentName == "unit") {
             mUnitSize = 1.f;
-            if (attr) {
-                mUnitSize = static_cast<ai_real>(attr.as_double());
-            }
-        } else if (name == "up_axis") {
+            XmlParser::getFloatAttribute(node, "meter", mUnitSize);
+        } else if (currentName == "up_axis") {
             std::string v;
-            XmlParser::getValueAsString(currentNode, v);
+            if (!XmlParser::getValueAsString(currentNode, v)) {
+                continue;
+            }
             if (v == "X_UP") {
                 mUpDirection = UP_X;
             } else if (v == "Z_UP") {
@@ -316,9 +347,9 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
             } else {
                 mUpDirection = UP_Y;
             }
-        } else if (name == "contributor") {
-            for (XmlNode currentChldNode : currentNode.children()) {
-                ReadMetaDataItem(currentChldNode, mAssetMetaData);
+        } else if (currentName == "contributor") {
+            for (XmlNode currentChildNode : currentNode.children()) {
+                ReadMetaDataItem(currentChildNode, mAssetMetaData);
             }
         } else {
             ReadMetaDataItem(currentNode, mAssetMetaData);
@@ -326,43 +357,32 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
     }
 }
 
-static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) {
-    for (size_t i = 0; i < key_renaming.size(); ++i) {
-        if (key_renaming[i].first == collada_key) {
-            found_index = i;
-            return true;
-        }
-    }
-    found_index = std::numeric_limits<size_t>::max();
-
-    return false;
-}
-
 // ------------------------------------------------------------------------------------------------
 // Reads a single string metadata item
 void ColladaParser::ReadMetaDataItem(XmlNode &node, StringMetaData &metadata) {
     const Collada::MetaKeyPairVector &key_renaming = GetColladaAssimpMetaKeysCamelCase();
-
     const std::string name = node.name();
     if (name.empty()) {
         return;
     }
 
     std::string v;
-    if (XmlParser::getValueAsString(node, v)) {
-        trim(v);
-        aiString aistr;
-        aistr.Set(v);
+    if (!XmlParser::getValueAsString(node, v)) {
+        return;
+    }
 
-        std::string camel_key_str(name);
-        ToCamelCase(camel_key_str);
+    trim(v);
+    aiString aistr;
+    aistr.Set(v);
 
-        size_t found_index;
-        if (FindCommonKey(camel_key_str, key_renaming, found_index)) {
-            metadata.emplace(key_renaming[found_index].second, aistr);
-        } else {
-            metadata.emplace(camel_key_str, aistr);
-        }
+    std::string camel_key_str(name);
+    ToCamelCase(camel_key_str);
+
+    size_t found_index;
+    if (FindCommonKey(camel_key_str, key_renaming, found_index)) {
+        metadata.emplace(key_renaming[found_index].second, aistr);
+    } else {
+        metadata.emplace(camel_key_str, aistr);
     }
 }
 
@@ -374,14 +394,8 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
     }
 
     std::string animName;
-    pugi::xml_attribute nameAttr = node.attribute("name");
-    if (nameAttr) {
-        animName = nameAttr.as_string();
-    } else {
-        pugi::xml_attribute idAttr = node.attribute("id");
-        if (idAttr) {
-            animName = idAttr.as_string();
-        } else {
+    if (!XmlParser::getStdStrAttribute(node, "name", animName)) {
+        if (!XmlParser::getStdStrAttribute( node, "id", animName )) {
             animName = std::string("animation_") + to_string(mAnimationClipLibrary.size());
         }
     }
@@ -389,17 +403,12 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
     std::pair<std::string, std::vector<std::string>> clip;
     clip.first = animName;
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string currentName = currentNode.name();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
         if (currentName == "instance_animation") {
-            pugi::xml_attribute url = currentNode.attribute("url");
-            if (url) {
-                const std::string urlName = url.as_string();
-                if (urlName[0] != '#') {
-                    throw DeadlyImportError("Unknown reference format");
-                }
-                clip.second.push_back(url.as_string());
-            }
+            std::string url;
+            readUrlAttribute(node, url);
+            clip.second.push_back(url);
         }
 
         if (clip.second.size() > 0) {
@@ -469,8 +478,8 @@ void ColladaParser::ReadAnimationLibrary(XmlNode &node) {
         return;
     }
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string currentName = currentNode.name();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
         if (currentName == "animation") {
             ReadAnimation(currentNode, &mAnims);
         }
@@ -486,17 +495,14 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
 
     // an <animation> element may be a container for grouping sub-elements or an animation channel
     // this is the channel collection by ID, in case it has channels
-    typedef std::map<std::string, AnimationChannel> ChannelMap;
+    using ChannelMap = std::map<std::string, AnimationChannel> ;
     ChannelMap channels;
     // this is the anim container in case we're a container
     Animation *anim = nullptr;
 
     // optional name given as an attribute
     std::string animName;
-    pugi::xml_attribute nameAttr = node.attribute("name");
-    if (nameAttr) {
-        animName = nameAttr.as_string();
-    } else {
+    if (!XmlParser::getStdStrAttribute(node, "name", animName)) {
         animName = "animation";
     }
 
@@ -506,8 +512,8 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
         animID = idAttr.as_string();
     }
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string currentName = currentNode.name();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
         if (currentName == "animation") {
             if (!anim) {
                 anim = new Animation;
@@ -520,23 +526,21 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
         } else if (currentName == "source") {
             ReadSource(currentNode);
         } else if (currentName == "sampler") {
-            pugi::xml_attribute sampler_id = currentNode.attribute("id");
-            if (sampler_id) {
-                std::string id = sampler_id.as_string();
-                ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
-
+            std::string id;
+            if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
                 // have it read into a channel
+                ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
                 ReadAnimationSampler(currentNode, newChannel->second);
             } else if (currentName == "channel") {
-                pugi::xml_attribute target = currentNode.attribute("target");
-                pugi::xml_attribute source = currentNode.attribute("source");
-                std::string source_name = source.as_string();
+                std::string source_name, target;
+                XmlParser::getStdStrAttribute(currentNode, "source", source_name);
+                XmlParser::getStdStrAttribute(currentNode, "target", target);
                 if (source_name[0] == '#') {
                     source_name = source_name.substr(1, source_name.size() - 1);
                 }
                 ChannelMap::iterator cit = channels.find(source_name);
                 if (cit != channels.end()) {
-                    cit->second.mTarget = target.as_string();
+                    cit->second.mTarget = target;
                 }
             }
         }
@@ -563,8 +567,8 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
 // ------------------------------------------------------------------------------------------------
 // Reads an animation sampler into the given anim channel
 void ColladaParser::ReadAnimationSampler(XmlNode &node, Collada::AnimationChannel &pChannel) {
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string currentName = currentNode.name();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
         if (currentName == "input") {
             if (XmlParser::hasAttribute(currentNode, "semantic")) {
                 std::string semantic, sourceAttr;
@@ -577,16 +581,17 @@ void ColladaParser::ReadAnimationSampler(XmlNode &node, Collada::AnimationChanne
                     }
                     source++;
 
-                    if (semantic == "INPUT")
+                    if (semantic == "INPUT") {
                         pChannel.mSourceTimes = source;
-                    else if (semantic == "OUTPUT")
+                    } else if (semantic == "OUTPUT") {
                         pChannel.mSourceValues = source;
-                    else if (semantic == "IN_TANGENT")
+                    } else if (semantic == "IN_TANGENT") {
                         pChannel.mInTanValues = source;
-                    else if (semantic == "OUT_TANGENT")
+                    } else if (semantic == "OUT_TANGENT") {
                         pChannel.mOutTanValues = source;
-                    else if (semantic == "INTERPOLATION")
+                    } else if (semantic == "INTERPOLATION") {
                         pChannel.mInterpolationValues = source;
+                    }
                 }
             }
         }
@@ -604,7 +609,6 @@ void ColladaParser::ReadControllerLibrary(XmlNode &node) {
         const std::string &currentName = currentNode.name();
         if (currentName != "controller") {
             continue;
-            ;
         }
         std::string id = node.attribute("id").as_string();
         mControllerLibrary[id] = Controller();
@@ -618,7 +622,7 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pControll
     // initial values
     pController.mType = Skin;
     pController.mMethod = Normalized;
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "morph") {
             pController.mType = Morph;
@@ -670,8 +674,8 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pControll
 // ------------------------------------------------------------------------------------------------
 // Reads the joint definitions for the given controller
 void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pController) {
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string currentName = currentNode.name();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
         if (currentName == "input") {
             const char *attrSemantic = currentNode.attribute("semantic").as_string();
             const char *attrSource = currentNode.attribute("source").as_string();
@@ -698,8 +702,8 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
     int vertexCount=0;
     XmlParser::getIntAttribute(node, "count", vertexCount);
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        std::string currentName = currentNode.name();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
         if (currentName == "input") {
             InputChannel channel;
 
@@ -763,9 +767,9 @@ void ColladaParser::ReadImageLibrary(XmlNode &node) {
         return;
     }
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string name = currentNode.name();
-        if (name == "image") {
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
+        if (currentName == "image") {
             std::string id = currentNode.attribute("id").as_string();
             mImageLibrary[id] = Image();
 
@@ -778,7 +782,7 @@ void ColladaParser::ReadImageLibrary(XmlNode &node) {
 // ------------------------------------------------------------------------------------------------
 // Reads an image entry into the given image
 void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string currentName = currentNode.name();
         if (currentName == "image") {
             // Ignore
@@ -798,23 +802,6 @@ void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
                 if (!pImage.mFileName.length()) {
                     pImage.mFileName = "unknown_texture";
                 }
-            } else if (mFormat == FV_1_5_n) {
-                // make sure we skip over mip and array initializations, which
-                // we don't support, but which could confuse the loader if
-                // they're not skipped.
-                //int v = currentNode.attribute("ref").as_int();
-                /*                if (v y) {
-                    ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
-                    continue;
-                }*/
-
-                //v = currentNode.attribute("mip_index").as_int();
-                /*if (attrib != -1 && v > 0) {
-                    ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
-                    continue;
-                }*/
-
-                // TODO: correctly jump over cube and volume maps?
             }
         } else if (mFormat == FV_1_5_n) {
             std::string value;
@@ -861,8 +848,7 @@ void ColladaParser::ReadMaterialLibrary(XmlNode &node) {
     }
 
     std::map<std::string, int> names;
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string currentName = currentNode.name();
+    for (XmlNode &currentNode : node.children()) {
         std::string id = currentNode.attribute("id").as_string();
         std::string name = currentNode.attribute("name").as_string();
         mMaterialLibrary[id] = Material();
@@ -891,11 +877,13 @@ void ColladaParser::ReadLightLibrary(XmlNode &node) {
         return;
     }
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "light") {
-            std::string id = currentNode.attribute("id").as_string();
-            ReadLight(currentNode, mLightLibrary[id] = Light());
+            std::string id;
+            if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
+                ReadLight(currentNode, mLightLibrary[id] = Light());
+            }
         }
     }
 }
@@ -907,18 +895,24 @@ void ColladaParser::ReadCameraLibrary(XmlNode &node) {
         return;
     }
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "camera") {
-            std::string id = currentNode.attribute("id").as_string();
+            std::string id;
+            if (!XmlParser::getStdStrAttribute(currentNode, "id", id)) {
+                continue;
+            }
 
             // create an entry and store it in the library under its ID
             Camera &cam = mCameraLibrary[id];
-            std::string name = currentNode.attribute("name").as_string();
+            std::string name;
+            if (!XmlParser::getStdStrAttribute(currentNode, "name", name)) {
+                continue;
+            }
             if (!name.empty()) {
                 cam.mName = name;
             }
-            ReadCamera(currentNode, cam);
+            ReadCamera(currentNode, cam);            
         }
     }
 }
@@ -926,14 +920,12 @@ void ColladaParser::ReadCameraLibrary(XmlNode &node) {
 // ------------------------------------------------------------------------------------------------
 // Reads a material entry into the given material
 void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) {
-    for (XmlNode currentNode : node.children()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "instance_effect") {
-            const char *url = currentNode.attribute("url").as_string();
-            if (url[0] != '#') {
-                throw DeadlyImportError("Unknown reference format");
-            }
-            pMaterial.mEffect = url + 1;
+            std::string url;
+            readUrlAttribute(currentNode, url);
+            pMaterial.mEffect = url.c_str();
         }
     }
 }
@@ -1032,7 +1024,7 @@ void ColladaParser::ReadEffectLibrary(XmlNode &node) {
         return;
     }
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "effect") {
             // read ID. Do I have to repeat my ranting about "optional" attributes?
@@ -1051,7 +1043,7 @@ void ColladaParser::ReadEffectLibrary(XmlNode &node) {
 // ------------------------------------------------------------------------------------------------
 // Reads an effect entry into the given effect
 void ColladaParser::ReadEffect(XmlNode &node, Collada::Effect &pEffect) {
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "profile_COMMON") {
             ReadEffectProfileCommon(currentNode, pEffect);
@@ -1256,8 +1248,6 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
         } else if (currentName == "technique") {
             std::string profile;
             XmlParser::getStdStrAttribute(currentNode, "profile", profile);
-            //const int _profile = GetAttribute("profile");
-            //const char *profile = mReader->getAttributeValue(_profile);
 
             // Some extensions are quite useful ... ReadSamplerProperties processes
             // several extensions in MAYA, OKINO and MAX3D profiles.
@@ -1330,7 +1320,7 @@ void ColladaParser::ReadGeometryLibrary(XmlNode &node) {
     if (node.empty()) {
         return;
     }
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "geometry") {
             // read ID. Another entry which is "optional" by design but obligatory in reality
@@ -1359,7 +1349,7 @@ void ColladaParser::ReadGeometry(XmlNode &node, Collada::Mesh &pMesh) {
     if (node.empty()) {
         return;
     }
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "mesh") {
             ReadMesh(currentNode, pMesh);
@@ -1383,7 +1373,9 @@ void ColladaParser::ReadMesh(XmlNode &node, Mesh &pMesh) {
             ReadSource(currentNode);
         } else if (currentName == "vertices") {
             ReadVertexData(currentNode, pMesh);
-        } else if (currentName == "triangles" || currentName == "lines" || currentName == "linestrips" || currentName == "polygons" || currentName == "polylist" || currentName == "trifans" || currentName == "tristrips") {
+        } else if (currentName == "triangles" || currentName == "lines" || currentName == "linestrips" ||
+                currentName == "polygons" || currentName == "polylist" || currentName == "trifans" ||
+                currentName == "tristrips") {
             ReadIndexData(currentNode, pMesh);
         }
     }
@@ -1541,16 +1533,11 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) {
                     acc.mSubOffset[1] = acc.mParams.size();
                 else if (name == "P")
                     acc.mSubOffset[2] = acc.mParams.size();
-                //  else if( name == "Q") acc.mSubOffset[3] = acc.mParams.size();
-                /* 4D uv coordinates are not supported in Assimp */
-
                 /* Generic extra data, interpreted as UV data, too*/
                 else if (name == "U")
                     acc.mSubOffset[0] = acc.mParams.size();
                 else if (name == "V")
                     acc.mSubOffset[1] = acc.mParams.size();
-                //else
-                //  DefaultLogger::get()->warn( format() << "Unknown accessor parameter \"" << name << "\". Ignoring data channel." );
             }
             if (XmlParser::hasAttribute(currentNode, "type")) {
                 // read data type
@@ -1575,7 +1562,7 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) {
 void ColladaParser::ReadVertexData(XmlNode &node, Mesh &pMesh) {
     // extract the ID of the <vertices> element. Not that we care, but to catch strange referencing schemes we should warn about
     XmlParser::getStdStrAttribute(node, "id", pMesh.mVertexID);
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "input") {
             ReadInputChannel(currentNode, pMesh.mPerVertexData);
@@ -1733,20 +1720,20 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
     // determine the expected number of indices
     size_t expectedPointCount = 0;
     switch (pPrimType) {
-    case Prim_Polylist: {
-        for (size_t i : pVCount)
-            expectedPointCount += i;
-        break;
-    }
-    case Prim_Lines:
-        expectedPointCount = 2 * pNumPrimitives;
-        break;
-    case Prim_Triangles:
-        expectedPointCount = 3 * pNumPrimitives;
-        break;
-    default:
-        // other primitive types don't state the index count upfront... we need to guess
-        break;
+        case Prim_Polylist: {
+            for (size_t i : pVCount)
+                expectedPointCount += i;
+            break;
+        }
+        case Prim_Lines:
+            expectedPointCount = 2 * pNumPrimitives;
+            break;
+        case Prim_Triangles:
+            expectedPointCount = 3 * pNumPrimitives;
+            break;
+        default:
+            // other primitive types don't state the index count upfront... we need to guess
+            break;
     }
 
     // and read all indices into a temporary array
@@ -1778,7 +1765,6 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
         } else {
             throw DeadlyImportError("Expected different index count in <p> element.");
         }
-
     } else if (expectedPointCount == 0 && (indices.size() % numOffsets) != 0) {
         throw DeadlyImportError("Expected different index count in <p> element.");
     }
@@ -2030,7 +2016,7 @@ void ColladaParser::ReadSceneLibrary(XmlNode &node) {
         return;
     }
 
-    for (XmlNode currentNode : node.children()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "visual_scene") {
             // read ID. Is optional according to the spec, but how on earth should a scene_instance refer to it then?
@@ -2197,11 +2183,8 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform
 // ------------------------------------------------------------------------------------------------
 // Processes bind_vertex_input and bind elements
 void ColladaParser::ReadMaterialVertexInputBinding(XmlNode &node, Collada::SemanticMappingTable &tbl) {
-    //XmlNodeIterator xmlIt(node);
-    //xmlIt.collectChildrenPreOrder(node);
-    //XmlNode currentNode;
     std::string name = node.name();
-    for (XmlNode currentNode : node.children()) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "bind_vertex_input") {
             Collada::InputSemanticMapEntry vn;
@@ -2296,8 +2279,8 @@ void ColladaParser::ReadScene(XmlNode &node) {
         return;
     }
 
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        const std::string currentName = currentNode.name();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
         if (currentName == "instance_visual_scene") {
             // should be the first and only occurrence
             if (mRootNode) {
@@ -2321,20 +2304,6 @@ void ColladaParser::ReadScene(XmlNode &node) {
     }
 }
 
-void ColladaParser::ReportWarning(const char *msg, ...) {
-    ai_assert(nullptr != msg);
-
-    va_list args;
-    va_start(args, msg);
-
-    char szBuffer[3000];
-    const int iLen = vsprintf(szBuffer, msg, args);
-    ai_assert(iLen > 0);
-
-    va_end(args);
-    ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer, iLen));
-}
-
 // ------------------------------------------------------------------------------------------------
 // Calculates the resulting transformation from all the given transform steps
 aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector<Transform> &pTransforms) const {

+ 12 - 22
code/AssetLib/Collada/ColladaParser.h

@@ -243,8 +243,6 @@ protected:
     void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
 
 protected:
-    void ReportWarning(const char *msg, ...);
-
     /** Calculates the resulting transformation from all the given transform steps */
     aiMatrix4x4 CalculateResultTransform(const std::vector<Collada::Transform> &pTransforms) const;
 
@@ -260,56 +258,55 @@ protected:
     std::string mFileName;
 
     // XML reader, member for everyday use
-    //irr::io::IrrXMLReader *mReader;
     XmlParser mXmlParser;
 
     /** All data arrays found in the file by ID. Might be referred to by actually
          everyone. Collada, you are a steaming pile of indirection. */
-    typedef std::map<std::string, Collada::Data> DataLibrary;
+    using DataLibrary = std::map<std::string, Collada::Data> ;
     DataLibrary mDataLibrary;
 
     /** Same for accessors which define how the data in a data array is accessed. */
-    typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
+    using AccessorLibrary = std::map<std::string, Collada::Accessor> ;
     AccessorLibrary mAccessorLibrary;
 
     /** Mesh library: mesh by ID */
-    typedef std::map<std::string, Collada::Mesh *> MeshLibrary;
+    using MeshLibrary = std::map<std::string, Collada::Mesh *>;
     MeshLibrary mMeshLibrary;
 
     /** node library: root node of the hierarchy part by ID */
-    typedef std::map<std::string, Collada::Node *> NodeLibrary;
+    using NodeLibrary = std::map<std::string, Collada::Node *>;
     NodeLibrary mNodeLibrary;
 
     /** Image library: stores texture properties by ID */
-    typedef std::map<std::string, Collada::Image> ImageLibrary;
+    using ImageLibrary = std::map<std::string, Collada::Image> ;
     ImageLibrary mImageLibrary;
 
     /** Effect library: surface attributes by ID */
-    typedef std::map<std::string, Collada::Effect> EffectLibrary;
+    using EffectLibrary = std::map<std::string, Collada::Effect> ;
     EffectLibrary mEffectLibrary;
 
     /** Material library: surface material by ID */
-    typedef std::map<std::string, Collada::Material> MaterialLibrary;
+    using MaterialLibrary = std::map<std::string, Collada::Material> ;
     MaterialLibrary mMaterialLibrary;
 
     /** Light library: surface light by ID */
-    typedef std::map<std::string, Collada::Light> LightLibrary;
+    using LightLibrary = std::map<std::string, Collada::Light> ;
     LightLibrary mLightLibrary;
 
     /** Camera library: surface material by ID */
-    typedef std::map<std::string, Collada::Camera> CameraLibrary;
+    using CameraLibrary = std::map<std::string, Collada::Camera> ;
     CameraLibrary mCameraLibrary;
 
     /** Controller library: joint controllers by ID */
-    typedef std::map<std::string, Collada::Controller> ControllerLibrary;
+    using ControllerLibrary = std::map<std::string, Collada::Controller> ;
     ControllerLibrary mControllerLibrary;
 
     /** Animation library: animation references by ID */
-    typedef std::map<std::string, Collada::Animation *> AnimationLibrary;
+    using AnimationLibrary = std::map<std::string, Collada::Animation *> ;
     AnimationLibrary mAnimationLibrary;
 
     /** Animation clip library: clip animation references by ID */
-    typedef std::vector<std::pair<std::string, std::vector<std::string>>> AnimationClipLibrary;
+    using AnimationClipLibrary = std::vector<std::pair<std::string, std::vector<std::string>>> ;
     AnimationClipLibrary mAnimationClipLibrary;
 
     /** Pointer to the root node. Don't delete, it just points to one of
@@ -334,13 +331,6 @@ protected:
     Collada::FormatVersion mFormat;
 };
 
-// ------------------------------------------------------------------------------------------------
-// Check for element match
-/*inline bool ColladaParser::IsElement(const char *pName) const {
-    ai_assert(mReader->getNodeType() == irr::io::EXN_ELEMENT);
-    return ::strcmp(mReader->getNodeName(), pName) == 0;
-}*/
-
 // ------------------------------------------------------------------------------------------------
 // Finds the item in the given library by its reference, throws if not found
 template <typename Type>

+ 5 - 0
code/AssetLib/FBX/FBXImporter.cpp

@@ -187,6 +187,11 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
 		// size relative to cm
 		float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
+        if (size_relative_to_cm == 0.0)
+        {
+			// BaseImporter later asserts that fileScale is non-zero.
+			ThrowException("The UnitScaleFactor must be non-zero");
+        }
 
 		// Set FBX file scale is relative to CM must be converted to M for
 		// assimp universal format (M)

+ 1 - 1
code/AssetLib/FBX/FBXMaterial.cpp

@@ -86,7 +86,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
     std::string templateName;
 
     // lower-case shading because Blender (for example) writes "Phong"
-    std::transform(shading.begin(), shading.end(), shading.begin(), Assimp::ToLower<char>);
+    std::transform(shading.data(), shading.data() + shading.size(), std::addressof(shading[0]), Assimp::ToLower<char>);
     if(shading == "phong") {
         templateName = "Material.FbxSurfacePhong";
     }

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 408 - 413
code/AssetLib/OpenGEX/OpenGEXImporter.cpp


+ 5 - 5
code/AssetLib/glTF/glTFAsset.inl

@@ -1060,7 +1060,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
 inline void Camera::Read(Value &obj, Asset & /*r*/) {
     type = MemberOrDefault(obj, "type", Camera::Perspective);
 
-    const char *subobjId = (type == Camera::Orthographic) ? "ortographic" : "perspective";
+    const char *subobjId = (type == Camera::Orthographic) ? "orthographic" : "perspective";
 
     Value *it = FindObject(obj, subobjId);
     if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters");
@@ -1071,10 +1071,10 @@ inline void Camera::Read(Value &obj, Asset & /*r*/) {
         perspective.zfar = MemberOrDefault(*it, "zfar", 100.f);
         perspective.znear = MemberOrDefault(*it, "znear", 0.01f);
     } else {
-        ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f);
-        ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f);
-        ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f);
-        ortographic.znear = MemberOrDefault(obj, "znear", 0.01f);
+        ortographic.xmag = MemberOrDefault(*it, "xmag", 1.f);
+        ortographic.ymag = MemberOrDefault(*it, "ymag", 1.f);
+        ortographic.zfar = MemberOrDefault(*it, "zfar", 100.f);
+        ortographic.znear = MemberOrDefault(*it, "znear", 0.01f);
     }
 }
 

+ 25 - 1
code/AssetLib/glTF2/glTF2Asset.inl

@@ -554,6 +554,16 @@ inline void BufferView::Read(Value &obj, Asset &r) {
     byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0));
     byteLength = MemberOrDefault(obj, "byteLength", size_t(0));
     byteStride = MemberOrDefault(obj, "byteStride", 0u);
+
+    // Check length
+    if ((byteOffset + byteLength) > buffer->byteLength) {
+        const uint8_t val_size = 64;
+
+        char val[val_size];
+
+        ai_snprintf(val, val_size, "%llu, %llu", (unsigned long long)byteOffset, (unsigned long long)byteLength);
+        throw DeadlyImportError("GLTF: Buffer view with offset/length (", val, ") is out of range.");
+    }
 }
 
 inline uint8_t *BufferView::GetPointer(size_t accOffset) {
@@ -627,6 +637,17 @@ inline void Accessor::Read(Value &obj, Asset &r) {
     const char *typestr;
     type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR;
 
+    // Check length
+    unsigned long long byteLength = (unsigned long long)GetBytesPerComponent() * (unsigned long long)count;
+    if ((byteOffset + byteLength) > bufferView->byteLength || (bufferView->byteOffset + byteOffset + byteLength) > bufferView->buffer->byteLength) {
+        const uint8_t val_size = 64;
+
+        char val[val_size];
+
+        ai_snprintf(val, val_size, "%llu, %llu", (unsigned long long)byteOffset, (unsigned long long)byteLength);
+        throw DeadlyImportError("GLTF: Accessor with offset/length (", val, ") is out of range.");
+    }
+
     if (Value *sparseValue = FindObject(obj, "sparse")) {
         sparse.reset(new Sparse);
         // count
@@ -1115,7 +1136,10 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
                     Mesh::AccessorList *vec = 0;
                     if (GetAttribVector(prim, attr, vec, undPos)) {
                         size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
-                        if ((*vec).size() <= idx) (*vec).resize(idx + 1);
+                        if ((*vec).size() != idx) {
+                            throw DeadlyImportError("GLTF: Invalid attribute: ", attr, ". All indices for indexed attribute semantics must start with 0 and be continuous positive integers: TEXCOORD_0, TEXCOORD_1, etc.");
+                        }
+                        (*vec).resize(idx + 1);
                         (*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint());
                     }
                 }

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1122 - 1123
code/AssetLib/glTF2/glTF2Importer.cpp


+ 2 - 4
code/Common/Version.cpp

@@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 */
 
-// Actually just a dummy, used by the compiler to build the precompiled header.
+// Actually just a dummy, used by the compiler to build the pre-compiled header.
 
 #include "ScenePrivate.h"
 #include <assimp/scene.h>
@@ -51,13 +51,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // --------------------------------------------------------------------------------
 // Legal information string - don't remove this.
 static const char *LEGAL_INFORMATION =
-
         "Open Asset Import Library (Assimp).\n"
         "A free C/C++ library to import various 3D file formats into applications\n\n"
-
         "(c) 2006-2020, assimp team\n"
         "License under the terms and conditions of the 3-clause BSD license\n"
-        "http://assimp.org\n";
+        "https://www.assimp.org\n";
 
 // ------------------------------------------------------------------------------------------------
 // Get legal string

+ 0 - 1
contrib/CMakeLists.txt

@@ -1 +0,0 @@
-

+ 12 - 12
contrib/openddlparser/CMakeLists.txt

@@ -6,20 +6,12 @@ SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
 SET ( OPENDDL_PARSER_VERSION ${OPENDDL_PARSER_VERSION_MAJOR}.${OPENDDL_PARSER_VERSION_MINOR}.${OPENDDL_PARSER_VERSION_PATCH} )
 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)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
     find_package(Threads)
@@ -31,6 +23,11 @@ if ( DDL_STATIC_LIBRARY )
 	add_definitions( -DOPENDDL_STATIC_LIBARY )
 endif()
 
+if (MSVC)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING")
+    add_definitions(-DGTEST_HAS_TR1_TUPLE=0)
+endif()
+
 add_definitions( -DOPENDDLPARSER_BUILD )
 add_definitions( -D_VARIADIC_MAX=10 )
 add_definitions( -DGTEST_HAS_PTHREAD=0 )
@@ -49,7 +46,7 @@ link_directories(
     ${CMAKE_HOME_DIRECTORY}/lib
 )
 
-set( CMAKE_MODULE_PATH  ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake )
+SET( CMAKE_MODULE_PATH  ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake )
 SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
@@ -97,6 +94,7 @@ SET ( openddl_parser_src
     include/openddlparser/OpenDDLStream.h
     include/openddlparser/DDLNode.h
     include/openddlparser/Value.h
+    include/openddlparser/TPoolAllocator.h
     README.md
 )
  
@@ -123,7 +121,6 @@ SET ( gtest_src
     ${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  
@@ -137,7 +134,10 @@ SET( openddl_parser_unittest_src
     test/OpenDDLIntegrationTest.cpp
     test/ValueTest.cpp
     test/OpenDDLDefectsTest.cpp
+	test/OssFuzzTest.cpp
+    test/main.cpp
 )
+add_definitions(-DOPENDDL_TEST_DATA="${CMAKE_CURRENT_LIST_DIR}/test/TestData")
 
 SOURCE_GROUP( code  FILES ${openddl_parser_unittest_src} )
 SOURCE_GROUP( gtest FILES ${gtest_src} )

+ 77 - 67
contrib/openddlparser/code/DDLNode.cpp

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -22,6 +22,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 #include <openddlparser/DDLNode.h>
 #include <openddlparser/OpenDDLParser.h>
+#include <openddlparser/OpenDDLStream.h>
 
 #include <algorithm>
 
@@ -29,77 +30,76 @@ BEGIN_ODDLPARSER_NS
 
 DDLNode::DllNodeList DDLNode::s_allocatedNodes;
 
-template<class T>
-inline
-static void releaseDataType( T *ptr ) {
-    if( ddl_nullptr == ptr ) {
+template <class T>
+inline static void releaseDataType(T *ptr) {
+    if (nullptr == ptr) {
         return;
     }
 
-    T *current( ddl_nullptr );
-    while( ptr ) {
+    T *current(nullptr);
+    while (ptr) {
         current = ptr;
         ptr = ptr->m_next;
         delete current;
     }
 }
 
-static void releaseReferencedNames( Reference *ref ) {
-    if( ddl_nullptr == ref ) {
+static void releaseReferencedNames(Reference *ref) {
+    if (nullptr == ref) {
         return;
     }
 
     delete ref;
 }
 
-DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent )
-: m_type( type )
-, m_name( name )
-, m_parent( parent )
-, m_children()
-, m_properties( ddl_nullptr )
-, m_value( ddl_nullptr )
-, m_dtArrayList( ddl_nullptr )
-, m_references( ddl_nullptr )
-, m_idx( idx ) {
-    if( m_parent ) {
-        m_parent->m_children.push_back( this );
+DDLNode::DDLNode(const std::string &type, const std::string &name, size_t idx, DDLNode *parent) :
+        m_type(type),
+        m_name(name),
+        m_parent(parent),
+        m_children(),
+        m_properties(nullptr),
+        m_value(nullptr),
+        m_dtArrayList(nullptr),
+        m_references(nullptr),
+        m_idx(idx) {
+    if (m_parent) {
+        m_parent->m_children.push_back(this);
     }
 }
 
 DDLNode::~DDLNode() {
     delete m_properties;
     delete m_value;
-    releaseReferencedNames( m_references );
+    releaseReferencedNames(m_references);
 
     delete m_dtArrayList;
-    m_dtArrayList = ddl_nullptr;
-    if( s_allocatedNodes[ m_idx ] == this ) {
-        s_allocatedNodes[ m_idx ] = ddl_nullptr;
+    m_dtArrayList = nullptr;
+    if (s_allocatedNodes[m_idx] == this) {
+        s_allocatedNodes[m_idx] = nullptr;
     }
-    for ( size_t i = 0; i<m_children.size(); i++ ){
-        delete m_children[ i ];
+    for (size_t i = 0; i < m_children.size(); i++) {
+        delete m_children[i];
     }
 }
 
-void DDLNode::attachParent( DDLNode *parent ) {
-    if( m_parent == parent ) {
+void DDLNode::attachParent(DDLNode *parent) {
+    if (m_parent == parent) {
         return;
     }
 
     m_parent = parent;
-    if( ddl_nullptr != m_parent ) {
-        m_parent->m_children.push_back( this );
+    if (nullptr != m_parent) {
+        m_parent->m_children.push_back(this);
     }
 }
 
 void DDLNode::detachParent() {
-    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 ) {
-            m_parent->m_children.erase( it );
+    if (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) {
+            m_parent->m_children.erase(it);
         }
-        m_parent = ddl_nullptr;
+        m_parent = nullptr;
     }
 }
 
@@ -111,7 +111,7 @@ const DDLNode::DllNodeList &DDLNode::getChildNodeList() const {
     return m_children;
 }
 
-void DDLNode::setType( const std::string &type ) {
+void DDLNode::setType(const std::string &type) {
     m_type = type;
 }
 
@@ -119,7 +119,7 @@ const std::string &DDLNode::getType() const {
     return m_type;
 }
 
-void DDLNode::setName( const std::string &name ) {
+void DDLNode::setName(const std::string &name) {
     m_name = name;
 }
 
@@ -127,8 +127,8 @@ const std::string &DDLNode::getName() const {
     return m_name;
 }
 
-void DDLNode::setProperties( Property *prop ) {
-    if(m_properties!=ddl_nullptr)
+void DDLNode::setProperties(Property *prop) {
+    if (m_properties != nullptr)
         delete m_properties;
     m_properties = prop;
 }
@@ -137,37 +137,37 @@ Property *DDLNode::getProperties() const {
     return m_properties;
 }
 
-bool DDLNode::hasProperty( const std::string &name ) {
-    const Property *prop( findPropertyByName( name ) );
-    return ( ddl_nullptr != prop );
+bool DDLNode::hasProperty(const std::string &name) {
+    const Property *prop(findPropertyByName(name));
+    return (nullptr != prop);
 }
 
 bool DDLNode::hasProperties() const {
-    return( ddl_nullptr != m_properties );
+    return (nullptr != m_properties);
 }
 
-Property *DDLNode::findPropertyByName( const std::string &name ) {
-    if( name.empty() ) {
-        return ddl_nullptr;
+Property *DDLNode::findPropertyByName(const std::string &name) {
+    if (name.empty()) {
+        return nullptr;
     }
 
-    if( ddl_nullptr == m_properties ) {
-        return ddl_nullptr;
+    if (nullptr == m_properties) {
+        return nullptr;
     }
 
-    Property *current( m_properties );
-    while( ddl_nullptr != current ) {
-        int res = strncmp( current->m_key->m_buffer, name.c_str(), name.size() );
-        if( 0 == res ) {
+    Property *current(m_properties);
+    while (nullptr != current) {
+        int res = strncmp(current->m_key->m_buffer, name.c_str(), name.size());
+        if (0 == res) {
             return current;
         }
         current = current->m_next;
     }
 
-    return ddl_nullptr;
+    return nullptr;
 }
 
-void DDLNode::setValue( Value *val ) {
+void DDLNode::setValue(Value *val) {
     m_value = val;
 }
 
@@ -175,7 +175,7 @@ Value *DDLNode::getValue() const {
     return m_value;
 }
 
-void DDLNode::setDataArrayList( DataArrayList  *dtArrayList ) {
+void DDLNode::setDataArrayList(DataArrayList *dtArrayList) {
     m_dtArrayList = dtArrayList;
 }
 
@@ -183,7 +183,7 @@ DataArrayList *DDLNode::getDataArrayList() const {
     return m_dtArrayList;
 }
 
-void DDLNode::setReferences( Reference *refs ) {
+void DDLNode::setReferences(Reference *refs) {
     m_references = refs;
 }
 
@@ -191,22 +191,32 @@ Reference *DDLNode::getReferences() const {
     return m_references;
 }
 
-void DDLNode::dump(IOStreamBase &/*stream*/) {
-    // Todo!    
+void DDLNode::dump(IOStreamBase &stream) {
+    if (!stream.isOpen()) {
+        return;
+    }
+
+    const std::string &type = this->getType();
+    stream.write("type = " + type);
+    Value::Iterator it(getValue());
+    while (it.hasNext()) {
+        Value *v = it.getNext();
+        v->dump(stream);
+    }
 }
 
-DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) {
-    const size_t idx( s_allocatedNodes.size() );
-    DDLNode *node = new DDLNode( type, name, idx, parent );
-    s_allocatedNodes.push_back( node );
-    
+DDLNode *DDLNode::create(const std::string &type, const std::string &name, DDLNode *parent) {
+    const size_t idx(s_allocatedNodes.size());
+    DDLNode *node = new DDLNode(type, name, idx, parent);
+    s_allocatedNodes.push_back(node);
+
     return node;
 }
 
 void DDLNode::releaseNodes() {
-    if( s_allocatedNodes.size() > 0 ) {
-        for( DDLNodeIt it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
-            if( *it ) {
+    if (s_allocatedNodes.size() > 0) {
+        for (DDLNodeIt it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++) {
+            if (*it) {
                 delete *it;
             }
         }

+ 66 - 78
contrib/openddlparser/code/OpenDDLCommon.cpp

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -20,17 +20,17 @@ 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/OpenDDLCommon.h>
 #include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/Value.h>
 
 BEGIN_ODDLPARSER_NS
 
-Text::Text( const char *buffer, size_t numChars )
-: m_capacity( 0 )
-, m_len( 0 )
-, m_buffer( ddl_nullptr ) {
-    set( buffer, numChars );
+Text::Text(const char *buffer, size_t numChars) :
+        m_capacity(0),
+        m_len(0),
+        m_buffer(nullptr) {
+    set(buffer, numChars);
 }
 
 Text::~Text() {
@@ -39,103 +39,98 @@ Text::~Text() {
 
 void Text::clear() {
     delete[] m_buffer;
-    m_buffer = ddl_nullptr;
+    m_buffer = nullptr;
     m_capacity = 0;
     m_len = 0;
 }
 
-void Text::set( const char *buffer, size_t numChars ) {
+void Text::set(const char *buffer, size_t numChars) {
     clear();
-    if( numChars > 0 ) {
+    if (numChars > 0) {
         m_len = numChars;
         m_capacity = m_len + 1;
-        m_buffer = new char[ m_capacity ];
-        strncpy( m_buffer, buffer, numChars );
-        m_buffer[ numChars ] = '\0';
+        m_buffer = new char[m_capacity];
+        strncpy(m_buffer, buffer, numChars);
+        m_buffer[numChars] = '\0';
     }
 }
 
-bool Text::operator == ( const std::string &name ) const {
-    if( m_len != name.size() ) {
+bool Text::operator==(const std::string &name) const {
+    if (m_len != name.size()) {
         return false;
     }
-    const int res( strncmp( m_buffer, name.c_str(), name.size() ) );
+    const int res(strncmp(m_buffer, name.c_str(), name.size()));
 
-    return ( 0 == res );
+    return (0 == res);
 }
 
-bool Text::operator == ( const Text &rhs ) const {
-    if( m_len != rhs.m_len ) {
+bool Text::operator==(const Text &rhs) const {
+    if (m_len != rhs.m_len) {
         return false;
     }
 
-    const int res( strncmp( m_buffer, rhs.m_buffer, m_len ) );
+    const int res(strncmp(m_buffer, rhs.m_buffer, m_len));
 
-    return ( 0 == res );
+    return (0 == res);
 }
 
-Name::Name( NameType type, Text *id )
-: m_type( type )
-, m_id( id ) {
+Name::Name(NameType type, Text *id) :
+        m_type(type), m_id(id) {
     // empty
 }
 
 Name::~Name() {
     delete m_id;
-    m_id = ddl_nullptr;
+    m_id = nullptr;
 }
 
-Name::Name( const Name &name ){
-    m_type=name.m_type;
-    m_id=new Text(name.m_id->m_buffer,name.m_id->m_len);
+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_referencedName( ddl_nullptr ) {
+Reference::Reference() :
+        m_numRefs(0), m_referencedName(nullptr) {
     // empty
 }
 
-Reference::Reference( size_t numrefs, Name **names )
-: m_numRefs( numrefs )
-, m_referencedName( ddl_nullptr ) {
-    if ( numrefs > 0 ) {
-        m_referencedName = new Name *[ numrefs ];
-        for ( size_t i = 0; i < numrefs; i++ ) {
-            m_referencedName[ i ] = names[i];
+Reference::Reference(size_t numrefs, Name **names) :
+        m_numRefs(numrefs), m_referencedName(nullptr) {
+    if (numrefs > 0) {
+        m_referencedName = new Name *[numrefs];
+        for (size_t i = 0; i < numrefs; i++) {
+            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_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]);
         }
     }
 }
 
 Reference::~Reference() {
-    for( size_t i = 0; i < m_numRefs; i++ ) {
-        delete m_referencedName[ i ];
+    for (size_t i = 0; i < m_numRefs; i++) {
+        delete m_referencedName[i];
     }
     m_numRefs = 0;
-    delete [] m_referencedName;
-    m_referencedName = ddl_nullptr;
+    delete[] m_referencedName;
+    m_referencedName = nullptr;
 }
 
 size_t Reference::sizeInBytes() {
-    if ( 0 == m_numRefs ) {
+    if (0 == m_numRefs) {
         return 0;
     }
 
-    size_t size( 0 );
-    for ( size_t i = 0; i < m_numRefs; i++ ) {
-        Name *name( m_referencedName[ i ] );
-        if ( ddl_nullptr != name ) {
+    size_t size(0);
+    for (size_t i = 0; i < m_numRefs; i++) {
+        Name *name(m_referencedName[i]);
+        if (nullptr != name) {
             size += name->m_id->m_len;
         }
     }
@@ -143,60 +138,53 @@ size_t Reference::sizeInBytes() {
     return size;
 }
 
-Property::Property( Text *id )
-: m_key( id )
-, m_value( ddl_nullptr )
-, m_ref( ddl_nullptr )
-, m_next( ddl_nullptr ) {
+Property::Property(Text *id) :
+        m_key(id), m_value(nullptr), m_ref(nullptr), m_next(nullptr) {
     // empty
 }
 
 Property::~Property() {
     delete m_key;
-    if(m_value!=ddl_nullptr)
+    if (m_value != nullptr)
         delete m_value;
-    if(m_ref!=ddl_nullptr)
-        delete(m_ref);
-    if(m_next!=ddl_nullptr)
+    if (m_ref != nullptr)
+        delete (m_ref);
+    if (m_next != nullptr)
         delete m_next;
 }
 
-DataArrayList::DataArrayList()
-: m_numItems( 0 )
-, m_dataList( ddl_nullptr )
-, m_next( ddl_nullptr )
-, m_refs(ddl_nullptr)
-, m_numRefs(0){
+DataArrayList::DataArrayList() :
+        m_numItems(0), m_dataList(nullptr), m_next(nullptr), m_refs(nullptr), m_numRefs(0) {
     // empty
 }
 
 DataArrayList::~DataArrayList() {
     delete m_dataList;
-    if(m_next!=ddl_nullptr)
+    if (m_next != nullptr)
         delete m_next;
-    if(m_refs!=ddl_nullptr)
+    if (m_refs != nullptr)
         delete m_refs;
 }
 
 size_t DataArrayList::size() {
-    size_t result( 0 );
-    if ( ddl_nullptr == m_next ) {
-        if ( m_dataList != ddl_nullptr ) {
+    size_t result(0);
+    if (nullptr == m_next) {
+        if (m_dataList != nullptr) {
             result = 1;
         }
         return result;
     }
 
-    DataArrayList *n( m_next );
-    while( ddl_nullptr != n ) {
+    DataArrayList *n(m_next);
+    while (nullptr != n) {
         result++;
         n = n->m_next;
     }
     return result;
 }
 
-Context::Context()
-: m_root( ddl_nullptr ) {
+Context::Context() :
+        m_root(nullptr) {
     // empty
 }
 
@@ -206,7 +194,7 @@ Context::~Context() {
 
 void Context::clear() {
     delete m_root;
-    m_root = ddl_nullptr;
+    m_root = nullptr;
 }
 
 END_ODDLPARSER_NS

+ 159 - 181
contrib/openddlparser/code/OpenDDLExport.cpp

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -20,10 +20,10 @@ 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/OpenDDLExport.h>
 #include <openddlparser/DDLNode.h>
-#include <openddlparser/Value.h>
+#include <openddlparser/OpenDDLExport.h>
 #include <openddlparser/OpenDDLParser.h>
+#include <openddlparser/Value.h>
 
 #include <sstream>
 
@@ -33,9 +33,8 @@ struct DDLNodeIterator {
     const DDLNode::DllNodeList &m_childs;
     size_t m_idx;
 
-    DDLNodeIterator( const DDLNode::DllNodeList &childs ) 
-    : m_childs( childs )
-    , m_idx( 0 ) {
+    DDLNodeIterator(const DDLNode::DllNodeList &childs) :
+            m_childs(childs), m_idx(0) {
         // empty
     }
 
@@ -43,10 +42,10 @@ struct DDLNodeIterator {
         // empty
     }
 
-    bool getNext( DDLNode **node ) {
-        if( m_childs.size() > (m_idx+1) ) {
+    bool getNext(DDLNode **node) {
+        if (m_childs.size() > (m_idx + 1)) {
             m_idx++;
-            *node = m_childs[ m_idx ];
+            *node = m_childs[m_idx];
             return true;
         }
 
@@ -55,65 +54,65 @@ struct DDLNodeIterator {
 
 private:
     DDLNodeIterator() ddl_no_copy;
-    DDLNodeIterator &operator = ( const DDLNodeIterator & ) ddl_no_copy;
+    DDLNodeIterator &operator=(const DDLNodeIterator &) ddl_no_copy;
 };
 
-static void writeLineEnd( std::string &statement ) {
+static void writeLineEnd(std::string &statement) {
     statement += "\n";
 }
 
-OpenDDLExport::OpenDDLExport( IOStreamBase *stream )
-: m_stream( stream ) {
-    if (ddl_nullptr == m_stream) {
+OpenDDLExport::OpenDDLExport(IOStreamBase *stream) :
+        m_stream(stream) {
+    if (nullptr == m_stream) {
         m_stream = new IOStreamBase();
     }
 }
 
 OpenDDLExport::~OpenDDLExport() {
-    if (ddl_nullptr != m_stream) {
+    if (nullptr != m_stream) {
         m_stream->close();
     }
     delete m_stream;
 }
 
-bool OpenDDLExport::exportContext( Context *ctx, const std::string &filename ) {
-    if( ddl_nullptr == ctx ) {
+bool OpenDDLExport::exportContext(Context *ctx, const std::string &filename) {
+    if (nullptr == ctx) {
         return false;
     }
 
-    DDLNode *root( ctx->m_root );
-    if ( ddl_nullptr == root ) {
+    DDLNode *root(ctx->m_root);
+    if (nullptr == root) {
         return true;
     }
 
     if (!filename.empty()) {
-        if (!m_stream->open( filename )) {
+        if (!m_stream->open(filename)) {
             return false;
         }
     }
 
-    const bool retValue( handleNode( root ) );
-    
+    const bool retValue(handleNode(root));
+
     return retValue;
 }
 
-bool OpenDDLExport::handleNode( DDLNode *node ) {
-    if( ddl_nullptr == node ) {
+bool OpenDDLExport::handleNode(DDLNode *node) {
+    if (nullptr == node) {
         return true;
     }
 
     const DDLNode::DllNodeList &childs = node->getChildNodeList();
-    if( childs.empty() ) {
+    if (childs.empty()) {
         return true;
     }
-    DDLNode *current( ddl_nullptr );
-    DDLNodeIterator it( childs );
+    DDLNode *current(nullptr);
+    DDLNodeIterator it(childs);
     std::string statement;
-    bool success( true );
-    while( it.getNext( &current ) ) {
-        if( ddl_nullptr != current ) {
-            success |= writeNode( current, statement );
-            if( !handleNode( current ) ) {
+    bool success(true);
+    while (it.getNext(&current)) {
+        if (nullptr != current) {
+            success |= writeNode(current, statement);
+            if (!handleNode(current)) {
                 success = false;
             }
         }
@@ -122,56 +121,57 @@ bool OpenDDLExport::handleNode( DDLNode *node ) {
     return success;
 }
 
-bool OpenDDLExport::writeToStream( const std::string &statement ) {
-    if (ddl_nullptr == m_stream ) {
+bool OpenDDLExport::writeToStream(const std::string &statement) {
+    if (nullptr == m_stream) {
         return false;
     }
 
-    if ( !statement.empty()) {
-        m_stream->write( statement );
+    if (!statement.empty()) {
+        m_stream->write(statement);
     }
 
     return true;
 }
 
-bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) {
-    writeNodeHeader( node, statement );
+bool OpenDDLExport::writeNode(DDLNode *node, std::string &statement) {
+    bool success(true);
+    writeNodeHeader(node, statement);
     if (node->hasProperties()) {
-        writeProperties( node, statement );
+        success |= writeProperties(node, statement);
     }
-    writeLineEnd( statement );
+    writeLineEnd(statement);
 
     statement = "}";
-    DataArrayList *al( node->getDataArrayList() );
-    if ( ddl_nullptr != al ) {
-        writeValueType( al->m_dataList->m_type, al->m_numItems, statement );
-        writeValueArray( al, statement );
+    DataArrayList *al(node->getDataArrayList());
+    if (nullptr != al) {
+        writeValueType(al->m_dataList->m_type, al->m_numItems, statement);
+        writeValueArray(al, statement);
     }
-    Value *v( node->getValue() );
-    if (ddl_nullptr != v ) {
-        writeValueType( v->m_type, 1, statement );
+    Value *v(node->getValue());
+    if (nullptr != v) {
+        writeValueType(v->m_type, 1, statement);
         statement = "{";
-        writeLineEnd( statement );
-        writeValue( v, statement );
+        writeLineEnd(statement);
+        writeValue(v, statement);
         statement = "}";
-        writeLineEnd( statement );
+        writeLineEnd(statement);
     }
     statement = "}";
-    writeLineEnd( statement );
+    writeLineEnd(statement);
 
-    writeToStream( statement );
+    writeToStream(statement);
 
     return true;
 }
 
-bool OpenDDLExport::writeNodeHeader( DDLNode *node, std::string &statement ) {
-    if (ddl_nullptr == node) {
+bool OpenDDLExport::writeNodeHeader(DDLNode *node, std::string &statement) {
+    if (nullptr == node) {
         return false;
     }
 
     statement += node->getType();
-    const std::string &name( node->getName() );
-    if ( !name.empty() ) {
+    const std::string &name(node->getName());
+    if (!name.empty()) {
         statement += " ";
         statement += "$";
         statement += name;
@@ -180,30 +180,30 @@ bool OpenDDLExport::writeNodeHeader( DDLNode *node, std::string &statement ) {
     return true;
 }
 
-bool OpenDDLExport::writeProperties( DDLNode *node, std::string &statement ) {
-    if ( ddl_nullptr == node ) {
+bool OpenDDLExport::writeProperties(DDLNode *node, std::string &statement) {
+    if (nullptr == node) {
         return false;
     }
 
-    Property *prop( node->getProperties() );
+    Property *prop(node->getProperties());
     // if no properties are there, return
-    if ( ddl_nullptr == prop ) {
+    if (nullptr == prop) {
         return true;
     }
 
-    if ( ddl_nullptr != prop ) {
+    if (nullptr != prop) {
         // for instance (attrib = "position", bla=2)
         statement += "(";
-        bool first( true );
-        while ( ddl_nullptr != prop ) {
+        bool first(true);
+        while (nullptr != prop) {
             if (!first) {
                 statement += ", ";
             } else {
                 first = false;
             }
-            statement += std::string( prop->m_key->m_buffer );
+            statement += std::string(prop->m_key->m_buffer);
             statement += " = ";
-            writeValue( prop->m_value, statement );
+            writeValue(prop->m_value, statement);
             prop = prop->m_next;
         }
 
@@ -213,19 +213,19 @@ bool OpenDDLExport::writeProperties( DDLNode *node, std::string &statement ) {
     return true;
 }
 
-bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std::string &statement ) {
-    if ( Value::ddl_types_max == type) {
+bool OpenDDLExport::writeValueType(Value::ValueType type, size_t numItems, std::string &statement) {
+    if (Value::ValueType::ddl_types_max == type) {
         return false;
     }
 
-    const std::string typeStr( getTypeToken( type ) );
+    const std::string typeStr(getTypeToken(type));
     statement += typeStr;
     // if we have an array to write
-    if ( numItems > 1 ) {
+    if (numItems > 1) {
         statement += "[";
-        char buffer[ 256 ];
-        ::memset( buffer, '\0', 256 * sizeof( char ) );
-        sprintf( buffer, "%d", static_cast<int>( numItems ) );
+        char buffer[256];
+        ::memset(buffer, '\0', 256 * sizeof(char));
+        sprintf(buffer, "%d", static_cast<int>(numItems));
         statement += buffer;
         statement += "]";
     }
@@ -233,115 +233,93 @@ bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std:
     return true;
 }
 
-bool OpenDDLExport::writeValue( Value *val, std::string &statement ) {
-    if (ddl_nullptr == val) {
+bool OpenDDLExport::writeValue(Value *val, std::string &statement) {
+    if (nullptr == val) {
         return false;
     }
 
-    switch ( val->m_type ) {
-        case Value::ddl_bool:
-            if ( true == val->getBool() ) {
+    switch (val->m_type) {
+        case Value::ValueType::ddl_bool:
+            if (true == val->getBool()) {
                 statement += "true";
             } else {
                 statement += "false";
             }
             break;
-        case Value::ddl_int8: 
-            {
-                std::stringstream stream;
-                const int i = static_cast<int>( val->getInt8() );
-                stream << i;
-                statement += stream.str();
-            }
-            break;
-        case Value::ddl_int16:
-            {
-                std::stringstream stream;
-                char buffer[ 256 ];
-                ::memset( buffer, '\0', 256 * sizeof( char ) );
-                sprintf( buffer, "%d", val->getInt16() );
-                statement += buffer;
-        }
-            break;
-        case Value::ddl_int32:
-            {
-                std::stringstream stream;
-                char buffer[ 256 ];
-                ::memset( buffer, '\0', 256 * sizeof( char ) );
-                const int i = static_cast< int >( val->getInt32() );
-                sprintf( buffer, "%d", i );
-                statement += buffer;
-            }
+        case Value::ValueType::ddl_int8 : {
+            std::stringstream stream;
+            const int i = static_cast<int>(val->getInt8());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_int16: {
+            std::stringstream stream;
+            char buffer[256];
+            ::memset(buffer, '\0', 256 * sizeof(char));
+            sprintf(buffer, "%d", val->getInt16());
+            statement += buffer;
+        } break;
+        case Value::ValueType::ddl_int32: {
+            std::stringstream stream;
+            char buffer[256];
+            ::memset(buffer, '\0', 256 * sizeof(char));
+            const int i = static_cast<int>(val->getInt32());
+            sprintf(buffer, "%d", i);
+            statement += buffer;
+        } break;
+        case Value::ValueType::ddl_int64: {
+            std::stringstream stream;
+            const int i = static_cast<int>(val->getInt64());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_unsigned_int8: {
+            std::stringstream stream;
+            const int i = static_cast<unsigned int>(val->getUnsignedInt8());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_unsigned_int16: {
+            std::stringstream stream;
+            const int i = static_cast<unsigned int>(val->getUnsignedInt16());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_unsigned_int32: {
+            std::stringstream stream;
+            const int i = static_cast<unsigned int>(val->getUnsignedInt32());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_unsigned_int64: {
+            std::stringstream stream;
+            const int i = static_cast<unsigned int>(val->getUnsignedInt64());
+            stream << i;
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_half:
             break;
-        case Value::ddl_int64:
-            {
-                std::stringstream stream;
-                const int i = static_cast< int >( val->getInt64() );
-                stream << i;
-                statement += stream.str();
-            }
+        case Value::ValueType::ddl_float: {
+            std::stringstream stream;
+            stream << val->getFloat();
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_double: {
+            std::stringstream stream;
+            stream << val->getDouble();
+            statement += stream.str();
+        } break;
+        case Value::ValueType::ddl_string: {
+            std::stringstream stream;
+            stream << val->getString();
+            statement += "\"";
+            statement += stream.str();
+            statement += "\"";
+        } break;
+        case Value::ValueType::ddl_ref:
             break;
-        case Value::ddl_unsigned_int8:
-            {
-                std::stringstream stream;
-                const int i = static_cast< unsigned int >( val->getUnsignedInt8() );
-                stream << i;
-                statement += stream.str();
-            }
-            break;
-        case Value::ddl_unsigned_int16:
-            {
-                std::stringstream stream;
-                const int i = static_cast< unsigned int >( val->getUnsignedInt16() );
-                stream << i;
-                statement += stream.str();
-            }
-            break;
-        case Value::ddl_unsigned_int32:
-            {
-                std::stringstream stream;
-                const int i = static_cast< unsigned int >( val->getUnsignedInt32() );
-                stream << i;
-                statement += stream.str();
-            }
-            break;
-        case Value::ddl_unsigned_int64:
-            {
-                std::stringstream stream;
-                const int i = static_cast< unsigned int >( val->getUnsignedInt64() );
-                stream << i;
-                statement += stream.str();
-            }
-            break;
-        case Value::ddl_half:
-            break;
-        case Value::ddl_float:
-            {
-                std::stringstream stream;
-                stream << val->getFloat();
-                statement += stream.str();
-            }
-            break;
-        case Value::ddl_double:
-            {
-                std::stringstream stream;
-                stream << val->getDouble();
-                statement += stream.str();
-            }
-            break;
-        case Value::ddl_string:
-            {
-                std::stringstream stream;
-                stream << val->getString();
-                statement += "\"";
-                statement += stream.str();
-                statement += "\"";
-             }
-            break;
-        case Value::ddl_ref:
-            break;
-        case Value::ddl_none:
-        case Value::ddl_types_max:
+        case Value::ValueType::ddl_none:
+        case Value::ValueType::ddl_types_max:
         default:
             break;
     }
@@ -349,8 +327,8 @@ bool OpenDDLExport::writeValue( Value *val, std::string &statement ) {
     return true;
 }
 
-bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) {
-    if (ddl_nullptr == al) {
+bool OpenDDLExport::writeValueArray(DataArrayList *al, std::string &statement) {
+    if (nullptr == al) {
         return false;
     }
 
@@ -358,17 +336,18 @@ bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement )
         return true;
     }
 
-    DataArrayList *nextDataArrayList = al ;
-    while (ddl_nullptr != nextDataArrayList) {
-        if (ddl_nullptr != nextDataArrayList) {
+    DataArrayList *nextDataArrayList = al;
+    Value *nextValue(nextDataArrayList->m_dataList);
+    while (nullptr != nextDataArrayList) {
+        if (nullptr != nextDataArrayList) {
             statement += "{ ";
-            Value *nextValue( nextDataArrayList->m_dataList );
-            size_t idx( 0 );
-            while (ddl_nullptr != nextValue) {
+            nextValue = nextDataArrayList->m_dataList;
+            size_t idx(0);
+            while (nullptr != nextValue) {
                 if (idx > 0) {
                     statement += ", ";
                 }
-                writeValue( nextValue, statement );
+                writeValue(nextValue, statement);
                 nextValue = nextValue->m_next;
                 idx++;
             }
@@ -381,4 +360,3 @@ bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement )
 }
 
 END_ODDLPARSER_NS
-

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 344 - 337
contrib/openddlparser/code/OpenDDLParser.cpp


+ 15 - 15
contrib/openddlparser/code/OpenDDLStream.cpp

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -37,22 +37,22 @@ std::string StreamFormatterBase::format(const std::string &statement) {
     return tmp;
 }
 
-IOStreamBase::IOStreamBase(StreamFormatterBase *formatter)
-    : m_formatter(formatter)
-    , m_file(ddl_nullptr) {
-    if (ddl_nullptr == m_formatter) {
+IOStreamBase::IOStreamBase(StreamFormatterBase *formatter) :
+        m_formatter(formatter),
+        m_file(nullptr) {
+    if (nullptr == m_formatter) {
         m_formatter = new StreamFormatterBase;
     }
 }
 
 IOStreamBase::~IOStreamBase() {
     delete m_formatter;
-    m_formatter = ddl_nullptr;
+    m_formatter = nullptr;
 }
 
 bool IOStreamBase::open(const std::string &name) {
     m_file = ::fopen(name.c_str(), "a");
-    if (m_file == ddl_nullptr) {
+    if (m_file == nullptr) {
         return false;
     }
 
@@ -60,33 +60,33 @@ bool IOStreamBase::open(const std::string &name) {
 }
 
 bool IOStreamBase::close() {
-    if (ddl_nullptr == m_file) {
+    if (nullptr == m_file) {
         return false;
     }
 
     ::fclose(m_file);
-    m_file = ddl_nullptr;
+    m_file = nullptr;
 
     return true;
 }
 
 bool IOStreamBase::isOpen() const {
-    return ( ddl_nullptr != m_file );
+    return (nullptr != m_file);
 }
 
-size_t IOStreamBase::read( size_t sizeToRead, std::string &statement ) {
-    if (ddl_nullptr == m_file) {
+size_t IOStreamBase::read(size_t sizeToRead, std::string &statement) {
+    if (nullptr == m_file) {
         return 0;
     }
-    
+
     statement.resize(sizeToRead);
-    const size_t readBytes = ::fread( &statement[0], 1, sizeToRead, m_file );
+    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) {
+    if (nullptr == m_file) {
         return 0;
     }
     std::string formatStatement = m_formatter->format(statement);

+ 194 - 196
contrib/openddlparser/code/Value.cpp

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -20,30 +20,30 @@ 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>
 #include <openddlparser/Value.h>
 
-#include <iostream>
 #include <cassert>
 
 BEGIN_ODDLPARSER_NS
 
-static Value::Iterator end( ddl_nullptr );
+static Value::Iterator end(nullptr);
 
-Value::Iterator::Iterator()
-: m_start( ddl_nullptr )
-, m_current( ddl_nullptr ) {
+Value::Iterator::Iterator() :
+        m_start(nullptr),
+        m_current(nullptr) {
     // empty
 }
 
-Value::Iterator::Iterator( Value *start )
-: m_start( start )
-, m_current( start ) {
+Value::Iterator::Iterator(Value *start) :
+        m_start(start),
+        m_current(start) {
     // empty
 }
 
-Value::Iterator::Iterator( const Iterator &rhs )
-: m_start( rhs.m_start )
-, m_current( rhs.m_current ) {
+Value::Iterator::Iterator(const Iterator &rhs) :
+        m_start(rhs.m_start),
+        m_current(rhs.m_current) {
     // empty
 }
 
@@ -52,36 +52,36 @@ Value::Iterator::~Iterator() {
 }
 
 bool Value::Iterator::hasNext() const {
-    if( ddl_nullptr == m_current ) {
+    if (nullptr == m_current) {
         return false;
     }
-    return ( ddl_nullptr != m_current->getNext() );
+    return (nullptr != m_current->getNext());
 }
 
 Value *Value::Iterator::getNext() {
-    if( !hasNext() ) {
-        return ddl_nullptr;
+    if (!hasNext()) {
+        return nullptr;
     }
 
-    Value *v( m_current->getNext() );
+    Value *v(m_current->getNext());
     m_current = v;
 
     return v;
 }
 
-const Value::Iterator Value::Iterator::operator++( int ) {
-    if( ddl_nullptr == m_current ) {
+const Value::Iterator Value::Iterator::operator++(int) {
+    if (nullptr == m_current) {
         return end;
     }
 
     m_current = m_current->getNext();
-    Iterator inst( m_current );
+    Iterator inst(m_current);
 
     return inst;
 }
 
-Value::Iterator &Value::Iterator::operator++( ) {
-    if( ddl_nullptr == m_current ) {
+Value::Iterator &Value::Iterator::operator++() {
+    if (nullptr == m_current) {
         return end;
     }
 
@@ -90,263 +90,261 @@ Value::Iterator &Value::Iterator::operator++( ) {
     return *this;
 }
 
-bool Value::Iterator::operator == ( const Iterator &rhs ) const {
-    return ( m_current == rhs.m_current );
+bool Value::Iterator::operator==(const Iterator &rhs) const {
+    return (m_current == rhs.m_current);
 }
 
-Value *Value::Iterator::operator->( ) const {
-    if(ddl_nullptr == m_current ) {
-        return ddl_nullptr;
+Value *Value::Iterator::operator->() const {
+    if (nullptr == m_current) {
+        return nullptr;
     }
     return m_current;
 }
 
-Value::Value( ValueType type )
-: m_type( type )
-, m_size( 0 )
-, m_data( ddl_nullptr )
-, m_next( ddl_nullptr ) {
+Value::Value(ValueType type) :
+        m_type(type),
+        m_size(0),
+        m_data(nullptr),
+        m_next(nullptr) {
     // empty
 }
 
 Value::~Value() {
-    if(m_data!=ddl_nullptr) {
-        if (m_type == ddl_ref ) {
-            Reference *tmp = (Reference *) m_data;
-            if (tmp != ddl_nullptr)
+    if (m_data != nullptr) {
+        if (m_type == ValueType::ddl_ref) {
+            Reference *tmp = (Reference *)m_data;
+            if (tmp != nullptr)
                 delete tmp;
-        }else
+        } else
             delete[] m_data;
-
     }
-    if(m_next!=ddl_nullptr)
+    if (m_next != nullptr)
         delete m_next;
 }
 
-void Value::setBool( bool value ) {
-    assert( ddl_bool == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setBool(bool value) {
+    assert(ValueType::ddl_bool == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 bool Value::getBool() {
-    assert( ddl_bool == m_type );
-    return ( *m_data == 1 );
+    assert(ValueType::ddl_bool == m_type);
+    return (*m_data == 1);
 }
 
-void Value::setInt8( int8 value ) {
-    assert( ddl_int8 == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setInt8(int8 value) {
+    assert(ValueType::ddl_int8 == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 int8 Value::getInt8() {
-    assert( ddl_int8 == m_type );
-    return ( int8 ) ( *m_data );
+    assert(ValueType::ddl_int8 == m_type);
+    return (int8)(*m_data);
 }
 
-void Value::setInt16( int16 value ) {
-    assert( ddl_int16 == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setInt16(int16 value) {
+    assert(ValueType::ddl_int16 == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 int16 Value::getInt16() {
-    assert( ddl_int16 == m_type );
+    assert(ValueType::ddl_int16 == m_type);
     int16 i;
-    ::memcpy( &i, m_data, m_size );
+    ::memcpy(&i, m_data, m_size);
     return i;
 }
 
-void Value::setInt32( int32 value ) {
-    assert( ddl_int32 == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setInt32(int32 value) {
+    assert(ValueType::ddl_int32 == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 int32 Value::getInt32() {
-    assert( ddl_int32 == m_type );
+    assert(ValueType::ddl_int32 == m_type);
     int32 i;
-    ::memcpy( &i, m_data, m_size );
+    ::memcpy(&i, m_data, m_size);
     return i;
 }
 
-void Value::setInt64( int64 value ) {
-    assert( ddl_int64 == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setInt64(int64 value) {
+    assert(ValueType::ddl_int64 == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 int64 Value::getInt64() {
-    assert( ddl_int64 == m_type );
+    assert(ValueType::ddl_int64 == m_type);
     int64 i;
-    ::memcpy( &i, m_data, m_size );
+    ::memcpy(&i, m_data, m_size);
     return i;
 }
 
-void Value::setUnsignedInt8( uint8 value ) {
-    assert( ddl_unsigned_int8 == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setUnsignedInt8(uint8 value) {
+    assert(ValueType::ddl_unsigned_int8 == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 uint8 Value::getUnsignedInt8() const {
-    assert( ddl_unsigned_int8 == m_type );
+    assert(ValueType::ddl_unsigned_int8 == m_type);
     uint8 i;
-    ::memcpy( &i, m_data, m_size );
+    ::memcpy(&i, m_data, m_size);
     return i;
 }
 
-void Value::setUnsignedInt16( uint16 value ) {
-    assert( ddl_unsigned_int16 == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setUnsignedInt16(uint16 value) {
+    assert(ValueType::ddl_unsigned_int16 == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 uint16 Value::getUnsignedInt16() const {
-    assert( ddl_unsigned_int16 == m_type );
+    assert(ValueType::ddl_unsigned_int16 == m_type);
     uint16 i;
-    ::memcpy( &i, m_data, m_size );
+    ::memcpy(&i, m_data, m_size);
     return i;
 }
 
-void Value::setUnsignedInt32( uint32 value ) {
-    assert( ddl_unsigned_int32 == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setUnsignedInt32(uint32 value) {
+    assert(ValueType::ddl_unsigned_int32 == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 uint32 Value::getUnsignedInt32() const {
-    assert( ddl_unsigned_int32 == m_type );
+    assert(ValueType::ddl_unsigned_int32 == m_type);
     uint32 i;
-    ::memcpy( &i, m_data, m_size );
+    ::memcpy(&i, m_data, m_size);
     return i;
 }
 
-void Value::setUnsignedInt64( uint64 value ) {
-    assert( ddl_unsigned_int64 == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setUnsignedInt64(uint64 value) {
+    assert(ValueType::ddl_unsigned_int64 == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 uint64 Value::getUnsignedInt64() const {
-    assert( ddl_unsigned_int64 == m_type );
+    assert(ValueType::ddl_unsigned_int64 == m_type);
     uint64 i;
-    ::memcpy( &i, m_data, m_size );
+    ::memcpy(&i, m_data, m_size);
     return i;
 }
 
-void Value::setFloat( float value ) {
-    assert( ddl_float == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setFloat(float value) {
+    assert(ValueType::ddl_float == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 float Value::getFloat() const {
-    if( m_type == ddl_float ) {
+    if (m_type == ValueType::ddl_float) {
         float v;
-        ::memcpy( &v, m_data, m_size );
-        return ( float ) v;
+        ::memcpy(&v, m_data, m_size);
+        return (float)v;
     } else {
         float tmp;
-        ::memcpy( &tmp, m_data, 4 );
-        return ( float ) tmp;
+        ::memcpy(&tmp, m_data, 4);
+        return (float)tmp;
     }
 }
 
-void Value::setDouble( double value ) {
-    assert( ddl_double == m_type );
-    ::memcpy( m_data, &value, m_size );
+void Value::setDouble(double value) {
+    assert(ValueType::ddl_double == m_type);
+    ::memcpy(m_data, &value, m_size);
 }
 
 double Value::getDouble() const {
-    if ( m_type == ddl_double ) {
+    if (m_type == ValueType::ddl_double) {
         double v;
-        ::memcpy( &v, m_data, m_size );
-        return ( float ) v;
-    }
-    else {
+        ::memcpy(&v, m_data, m_size);
+        return (float)v;
+    } else {
         double tmp;
-        ::memcpy( &tmp, m_data, 4 );
-        return ( double ) tmp;
+        ::memcpy(&tmp, m_data, 4);
+        return (double)tmp;
     }
 }
 
-void Value::setString( const std::string &str ) {
-    assert( ddl_string == m_type );
-    ::memcpy( m_data, str.c_str(), str.size() );
-    m_data[ str.size() ] = '\0';
+void Value::setString(const std::string &str) {
+    assert(ValueType::ddl_string == m_type);
+    ::memcpy(m_data, str.c_str(), str.size());
+    m_data[str.size()] = '\0';
 }
 
 const char *Value::getString() const {
-    assert( ddl_string == m_type );
-    return (const char*) m_data;
+    assert(ValueType::ddl_string == m_type);
+    return (const char *)m_data;
 }
 
-void Value::setRef( Reference *ref ) {
-    assert( ddl_ref == m_type );
+void Value::setRef(Reference *ref) {
+    assert(ValueType::ddl_ref == m_type);
 
-    if ( ddl_nullptr != ref ) {
-        const size_t sizeInBytes( ref->sizeInBytes() );
-        if ( sizeInBytes > 0 ) {
-            if ( ddl_nullptr != m_data ) {
-                delete [] m_data;
+    if (nullptr != ref) {
+        const size_t sizeInBytes(ref->sizeInBytes());
+        if (sizeInBytes > 0) {
+            if (nullptr != m_data) {
+                delete[] m_data;
             }
 
-            m_data = (unsigned char*) new Reference(*ref);
+            m_data = (unsigned char *)new Reference(*ref);
         }
     }
 }
 
 Reference *Value::getRef() const {
-    assert( ddl_ref == m_type );
+    assert(ValueType::ddl_ref == m_type);
 
-    return (Reference*) m_data;
+    return (Reference *)m_data;
 }
 
-void Value::dump( IOStreamBase &/*stream*/ ) {
-    switch( m_type ) {
-        case ddl_none:
-            std::cout << "None" << std::endl;
+void Value::dump(IOStreamBase &stream) {
+    switch (m_type) {
+        case ValueType::ddl_none:
+            stream.write("None\n");
             break;
-        case ddl_bool:
-            std::cout << getBool() << std::endl;
+        case ValueType::ddl_bool:
+            stream.write(std::to_string(getBool()) + "\n");
             break;
-        case ddl_int8:
-            std::cout << getInt8() << std::endl;
+        case ValueType::ddl_int8:
+            stream.write(std::to_string(getInt8()) + "\n");
             break;
-        case ddl_int16:
-            std::cout << getInt16() << std::endl;
+        case ValueType::ddl_int16:
+            stream.write(std::to_string(getInt16()) + "\n");
             break;
-        case ddl_int32:
-            std::cout << getInt32() << std::endl;
+        case ValueType::ddl_int32:
+            stream.write(std::to_string(getInt32()) + "\n");
             break;
-        case ddl_int64:
-            std::cout << getInt64() << std::endl;
+        case ValueType::ddl_int64:
+            stream.write(std::to_string(getInt64()) + "\n");
             break;
-        case ddl_unsigned_int8:
-            std::cout << "Not supported" << std::endl;
+        case ValueType::ddl_unsigned_int8:
+            stream.write("Not supported\n");
             break;
-        case ddl_unsigned_int16:
-            std::cout << "Not supported" << std::endl;
+        case ValueType::ddl_unsigned_int16:
+            stream.write("Not supported\n");
             break;
-        case ddl_unsigned_int32:
-            std::cout << "Not supported" << std::endl;
+        case ValueType::ddl_unsigned_int32:
+            stream.write("Not supported\n");
             break;
-        case ddl_unsigned_int64:
-            std::cout << "Not supported" << std::endl;
+        case ValueType::ddl_unsigned_int64:
+            stream.write("Not supported\n");
             break;
-        case ddl_half:
-            std::cout << "Not supported" << std::endl;
+        case ValueType::ddl_half:
+            stream.write("Not supported\n");
             break;
-        case ddl_float:
-            std::cout << getFloat() << std::endl;
+        case ValueType::ddl_float:
+            stream.write(std::to_string(getFloat()) + "\n");
             break;
-        case ddl_double:
-            std::cout << getDouble() << std::endl;
+        case ValueType::ddl_double:
+            stream.write(std::to_string(getDouble()) + "\n");
             break;
-        case ddl_string:
-            std::cout << getString() << std::endl;
+        case ValueType::ddl_string:
+            stream.write(std::string(getString()) + "\n");
             break;
-        case ddl_ref:
-            std::cout << "Not supported" << std::endl;
+        case ValueType::ddl_ref:
+            stream.write("Not supported\n");
             break;
         default:
             break;
     }
 }
 
-void Value::setNext( Value *next ) {
+void Value::setNext(Value *next) {
     m_next = next;
 }
 
@@ -354,86 +352,86 @@ Value *Value::getNext() const {
     return m_next;
 }
 
-size_t Value::size() const{
-    size_t result=1;
-    Value *n=m_next;
-    while( n!=ddl_nullptr) {
+size_t Value::size() const {
+    size_t result = 1;
+    Value *n = m_next;
+    while (n != nullptr) {
         result++;
-        n=n->m_next;
+        n = n->m_next;
     }
     return result;
 }
 
-Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
-    if( type == Value::ddl_none || Value::ddl_types_max == type ) {
-        return ddl_nullptr;
+Value *ValueAllocator::allocPrimData(Value::ValueType type, size_t len) {
+    if (type == Value::ValueType::ddl_none || Value::ValueType::ddl_types_max == type) {
+        return nullptr;
     }
 
-    Value *data = new Value( type );
-    switch( type ) {
-        case Value::ddl_bool:
-            data->m_size = sizeof( bool );
+    Value *data = new Value(type);
+    switch (type) {
+        case Value::ValueType::ddl_bool:
+            data->m_size = sizeof(bool);
             break;
-        case Value::ddl_int8:
-            data->m_size = sizeof( int8 );
+        case Value::ValueType::ddl_int8:
+            data->m_size = sizeof(int8);
             break;
-        case Value::ddl_int16:
-            data->m_size = sizeof( int16 );
+        case Value::ValueType::ddl_int16:
+            data->m_size = sizeof(int16);
             break;
-        case Value::ddl_int32:
-            data->m_size = sizeof( int32 );
+        case Value::ValueType::ddl_int32:
+            data->m_size = sizeof(int32);
             break;
-        case Value::ddl_int64:
-            data->m_size = sizeof( int64 );
+        case Value::ValueType::ddl_int64:
+            data->m_size = sizeof(int64);
             break;
-        case Value::ddl_unsigned_int8:
-            data->m_size = sizeof( uint8 );
+        case Value::ValueType::ddl_unsigned_int8:
+            data->m_size = sizeof(uint8);
             break;
-        case Value::ddl_unsigned_int16:
-            data->m_size = sizeof( uint16 );
+        case Value::ValueType::ddl_unsigned_int16:
+            data->m_size = sizeof(uint16);
             break;
-        case Value::ddl_unsigned_int32:
-            data->m_size = sizeof( uint32 );
+        case Value::ValueType::ddl_unsigned_int32:
+            data->m_size = sizeof(uint32);
             break;
-        case Value::ddl_unsigned_int64:
-            data->m_size = sizeof( uint64 );
+        case Value::ValueType::ddl_unsigned_int64:
+            data->m_size = sizeof(uint64);
             break;
-        case Value::ddl_half:
-            data->m_size = sizeof( short );
+        case Value::ValueType::ddl_half:
+            data->m_size = sizeof(short);
             break;
-        case Value::ddl_float:
-            data->m_size = sizeof( float );
+        case Value::ValueType::ddl_float:
+            data->m_size = sizeof(float);
             break;
-        case Value::ddl_double:
-            data->m_size = sizeof( double );
+        case Value::ValueType::ddl_double:
+            data->m_size = sizeof(double);
             break;
-        case Value::ddl_string:
-            data->m_size = sizeof( char )*(len+1);
+        case Value::ValueType::ddl_string:
+            data->m_size = sizeof(char) * (len + 1);
             break;
-        case Value::ddl_ref:
+        case Value::ValueType::ddl_ref:
             data->m_size = 0;
             break;
-        case Value::ddl_none:
-        case Value::ddl_types_max:
+        case Value::ValueType::ddl_none:
+        case Value::ValueType::ddl_types_max:
         default:
             break;
     }
 
-    if( data->m_size ) {
-        data->m_data = new unsigned char[ data->m_size ];
-        ::memset(data->m_data,0,data->m_size);
+    if (data->m_size) {
+        data->m_data = new unsigned char[data->m_size];
+        ::memset(data->m_data, 0, data->m_size);
     }
 
     return data;
 }
 
-void ValueAllocator::releasePrimData( Value **data ) {
-    if( !data ) {
+void ValueAllocator::releasePrimData(Value **data) {
+    if (!data) {
         return;
     }
 
     delete *data;
-    *data = ddl_nullptr;
+    *data = nullptr;
 }
 
 END_ODDLPARSER_NS

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

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -24,8 +24,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include <openddlparser/OpenDDLCommon.h>
 
-#include <vector>
 #include <string>
+#include <vector>
 
 BEGIN_ODDLPARSER_NS
 
@@ -53,10 +53,10 @@ public:
     friend class OpenDDLParser;
 
     /// @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;
+    typedef std::vector<DDLNode *>::iterator DDLNodeIt;
 
 public:
     ///	@brief  The class destructor.
@@ -64,7 +64,7 @@ public:
 
     ///	@brief  Will attach a parent node instance, an older one will be released.
     /// @param  parent      [in] The parent node instance.
-    void attachParent( DDLNode *parent );
+    void attachParent(DDLNode *parent);
 
     /// @brief  Will try to detach a parent node instance, if there is any.
     void detachParent();
@@ -79,7 +79,7 @@ public:
 
     /// Set the type of the DDLNode instance.
     /// @param  type    [in] The type.
-    void setType( const std::string &type );
+    void setType(const std::string &type);
 
     /// @brief  Returns the type of the DDLNode instance.
     /// @return The type of the DDLNode instance.
@@ -87,7 +87,7 @@ public:
 
     /// Set the name of the DDLNode instance.
     /// @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.
     /// @return The name of the DDLNode instance.
@@ -95,7 +95,7 @@ public:
 
     /// @brief  Set a new 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.
     ///	@return The first property of the assigned property set.
@@ -104,7 +104,7 @@ public:
     ///	@brief  Looks for a given property.
     /// @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.
-    bool hasProperty( const std::string &name );
+    bool hasProperty(const std::string &name);
 
     ///	@brief  Will return true, if any properties are assigned to the node instance.
     ///	@return True, if properties are assigned.
@@ -113,11 +113,11 @@ public:
     ///	@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.
     /// @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.
     /// @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.
     ///	@return The first property of the assigned value set.
@@ -125,7 +125,7 @@ public:
 
     /// @brief  Set a new DataArrayList.
     /// @param  dtArrayList [in] The DataArrayList instance.
-    void setDataArrayList( DataArrayList *dtArrayList );
+    void setDataArrayList(DataArrayList *dtArrayList);
 
     ///	@brief  Returns the DataArrayList.
     ///	@return The DataArrayList.
@@ -133,7 +133,7 @@ public:
 
     /// @brief  Set a new 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.
     ///	@return The first property of the assigned Reference set.
@@ -148,20 +148,20 @@ public:
     ///	@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.
-    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 = nullptr);
 
 private:
-    DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent = ddl_nullptr );
+    DDLNode(const std::string &type, const std::string &name, size_t idx, DDLNode *parent = nullptr);
     DDLNode();
-    DDLNode( const DDLNode & ) ddl_no_copy;
-    DDLNode &operator = ( const DDLNode & ) ddl_no_copy;
+    DDLNode(const DDLNode &) ddl_no_copy;
+    DDLNode &operator=(const DDLNode &) ddl_no_copy;
     static void releaseNodes();
 
 private:
     std::string m_type;
     std::string m_name;
     DDLNode *m_parent;
-    std::vector<DDLNode*> m_children;
+    std::vector<DDLNode *> m_children;
     Property *m_properties;
     Value *m_value;
     DataArrayList *m_dtArrayList;

+ 74 - 75
contrib/openddlparser/include/openddlparser/OpenDDLCommon.h

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -23,49 +23,49 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include <cstddef>
-#include <vector>
 #include <string>
+#include <vector>
 
 #include <stdio.h>
 #include <string.h>
 #ifndef _WIN32
-#  include <inttypes.h>
+#include <inttypes.h>
 #endif
 
-#if defined(_MSC_VER) && !defined( OPENDDL_STATIC_LIBARY )
+#if defined(_MSC_VER) && !defined(OPENDDL_STATIC_LIBARY)
 
-#   define TAG_DLL_EXPORT __declspec(dllexport)
-#   define TAG_DLL_IMPORT __declspec(dllimport )
-#   ifdef OPENDDLPARSER_BUILD
-#       define DLL_ODDLPARSER_EXPORT TAG_DLL_EXPORT
-#   else
-#       define DLL_ODDLPARSER_EXPORT TAG_DLL_IMPORT
-#   endif // OPENDDLPARSER_BUILD
-#   pragma warning( disable : 4251 )
+#define TAG_DLL_EXPORT __declspec(dllexport)
+#define TAG_DLL_IMPORT __declspec(dllimport)
+#ifdef OPENDDLPARSER_BUILD
+#define DLL_ODDLPARSER_EXPORT TAG_DLL_EXPORT
 #else
-#   define DLL_ODDLPARSER_EXPORT
+#define DLL_ODDLPARSER_EXPORT TAG_DLL_IMPORT
+#endif // OPENDDLPARSER_BUILD
+#pragma warning(disable : 4251)
+#else
+#define DLL_ODDLPARSER_EXPORT
 #endif // _WIN32
 
 // Namespace declarations, override this to avoid any conflicts
 #define BEGIN_ODDLPARSER_NS namespace ODDLParser {
-#define END_ODDLPARSER_NS   } // namespace ODDLParser
-#define USE_ODDLPARSER_NS   using namespace ODDLParser;
+#define END_ODDLPARSER_NS } // namespace ODDLParser
+#define USE_ODDLPARSER_NS using namespace ODDLParser;
 
 BEGIN_ODDLPARSER_NS
 
 // We will use C++11 optional
 #ifndef OPENDDL_NO_USE_CPP11
-    // All C++11 constructs
-#   define ddl_nullptr nullptr
-#   define ddl_override override
-#   define ddl_final final
-#   define ddl_no_copy = delete
+// All C++11 constructs
+#define nullptr nullptr
+#define ddl_override override
+#define ddl_final final
+#define ddl_no_copy = delete
 #else
-    // Fall-back for older compilers
-#   define ddl_nullptr NULL
-#   define ddl_override
-#   define ddl_final
-#   define ddl_no_copy
+// Fall-back for older compilers
+#define nullptr NULL
+#define ddl_override
+#define ddl_final
+#define ddl_no_copy
 #endif // OPENDDL_NO_USE_CPP11
 
 // Forward declarations
@@ -80,36 +80,36 @@ struct DataArrayList;
 
 // Platform-specific typedefs
 #ifdef _WIN32
-typedef signed __int64    int64_impl;
-typedef unsigned __int64  uint64_impl;
+typedef signed __int64 int64_impl;
+typedef unsigned __int64 uint64_impl;
 #else
-typedef int64_t           int64_impl;
-typedef uint64_t          uint64_impl;
+typedef int64_t int64_impl;
+typedef uint64_t uint64_impl;
 #endif
 
 // OpenDDL-specific data typedefs
-typedef signed char       int8;    ///< Signed integer, 1 byte
-typedef signed short      int16;   ///< Signed integer, 2 byte
-typedef signed int        int32;   ///< Signed integer, 4 byte
-typedef int64_impl        int64;   ///< Signed integer, 8 byte
-typedef unsigned char     uint8;   ///< Unsigned integer, 1 byte
-typedef unsigned short    uint16;  ///< Unsigned integer, 2 byte
-typedef unsigned int      uint32;  ///< Unsigned integer, 4 byte
-typedef uint64_impl       uint64;  ///< Unsigned integer, 8 byte
+using int8 = signed char; ///< Signed integer, 1 byte
+using int16 = signed short; ///< Signed integer, 2 byte
+using int32 = signed int; ///< Signed integer, 4 byte
+using int64 = int64_impl; ///< Signed integer, 8 byte
+using uint8 = unsigned char; ///< Unsigned integer, 1 byte
+using uint16 = unsigned short ; ///< Unsigned integer, 2 byte
+using uint32 = unsigned int; ///< Unsigned integer, 4 byte
+using uint64 = uint64_impl ; ///< Unsigned integer, 8 byte
 
 ///	@brief  Stores a text.
 ///
 /// A text is stored in a simple character buffer. Texts buffer can be
 /// greater than the number of stored characters in them.
 struct DLL_ODDLPARSER_EXPORT Text {
-    size_t m_capacity;  ///< The capacity of the text.
-    size_t m_len;       ///< The length of the text.
-    char *m_buffer;     ///< The buffer with the text.
+    size_t m_capacity; ///< The capacity of the text.
+    size_t m_len; ///< The length of the text.
+    char *m_buffer; ///< The buffer with the text.
 
     ///	@brief  The constructor with a given text buffer.
     /// @param  buffer      [in] The buffer.
     /// @param  numChars    [in] The number of characters in the buffer.
-    Text( const char *buffer, size_t numChars );
+    Text(const char *buffer, size_t numChars);
 
     ///	@brief  The destructor.
     ~Text();
@@ -120,55 +120,54 @@ struct DLL_ODDLPARSER_EXPORT Text {
     ///	@brief  Set a new text.
     /// @param  buffer      [in] The buffer.
     /// @param  numChars    [in] The number of characters in the buffer.
-    void set( const char *buffer, size_t numChars );
+    void set(const char *buffer, size_t numChars);
 
     ///	@brief  The compare operator for std::strings.
-    bool operator == ( const std::string &name ) const;
+    bool operator==(const std::string &name) const;
 
     ///	@brief  The compare operator for Texts.
-    bool operator == ( const Text &rhs ) const;
+    bool operator==(const Text &rhs) const;
 
 private:
-    Text( const Text & ) ddl_no_copy;
-    Text &operator = ( const Text & ) ddl_no_copy;
+    Text(const Text &) ddl_no_copy;
+    Text &operator=(const Text &) ddl_no_copy;
 };
 
 ///	@brief  Description of the type of a name.
 enum NameType {
     GlobalName, ///< Name is global.
-    LocalName   ///< Name is local.
+    LocalName ///< Name is local.
 };
 
 ///	@brief  Stores an OpenDDL-specific name
 struct DLL_ODDLPARSER_EXPORT Name {
-    NameType    m_type; ///< The type of the name ( @see NameType ).
-    Text        *m_id;  ///< The id.
+    NameType m_type; ///< The type of the name ( @see NameType ).
+    Text *m_id; ///< The id.
 
     ///	@brief  The constructor with the type and the id.
     ///	@param  type    [in] The name type.
     ///	@param  id      [in] The id.
-    Name( NameType type, Text *id );
-    Name( const Name &name );
+    Name(NameType type, Text *id);
+    Name(const Name &name);
     ///	@brief  The destructor.
     ~Name();
 
 private:
-
-    Name &operator = ( const Name& ) ddl_no_copy;
+    Name &operator=(const Name &) ddl_no_copy;
 };
 
 ///	@brief  Stores a bundle of references.
 struct DLL_ODDLPARSER_EXPORT Reference {
-    size_t   m_numRefs;         ///< The number of stored references.
-    Name   **m_referencedName;  ///< The reference names.
+    size_t m_numRefs; ///< The number of stored references.
+    Name **m_referencedName; ///< The reference names.
 
     ///	@brief  The default constructor.
     Reference();
-    Reference( const Reference &ref );
+    Reference(const Reference &ref);
     ///	@brief  The constructor with an array of ref names.
     /// @param  numrefs     [in] The number of ref names.
     /// @param  names       [in] The ref names.
-    Reference( size_t numrefs, Name **names );
+    Reference(size_t numrefs, Name **names);
 
     ///	@brief  The destructor.
     ~Reference();
@@ -178,38 +177,38 @@ struct DLL_ODDLPARSER_EXPORT Reference {
     size_t sizeInBytes();
 
 private:
-    Reference &operator = ( const Reference & ) ddl_no_copy;
+    Reference &operator=(const Reference &) ddl_no_copy;
 };
 
 ///	@brief  Stores a property list.
 struct DLL_ODDLPARSER_EXPORT Property {
-    Text       *m_key;      ///< The identifier / key of the property.
-    Value      *m_value;    ///< The value assigned to its key / id ( ddl_nullptr if none ).
-    Reference  *m_ref;      ///< References assigned to its key / id ( ddl_nullptr if none ).
-    Property   *m_next;     ///< The next property ( ddl_nullptr if none ).
+    Text *m_key; ///< The identifier / key of the property.
+    Value *m_value; ///< The value assigned to its key / id ( ddl_nullptr if none ).
+    Reference *m_ref; ///< References assigned to its key / id ( ddl_nullptr if none ).
+    Property *m_next; ///< The next property ( ddl_nullptr if none ).
 
     ///	@brief  The default constructor.
     Property();
 
     ///	@brief  The constructor for initialization.
     /// @param  id      [in] The identifier
-    Property( Text *id );
+    Property(Text *id);
 
     ///	@brief  The destructor.
     ~Property();
 
 private:
-    Property( const Property & ) ddl_no_copy;
-    Property &operator = ( const Property & ) ddl_no_copy;
+    Property(const Property &) ddl_no_copy;
+    Property &operator=(const Property &) ddl_no_copy;
 };
 
 ///	@brief  Stores a data array list.
 struct DLL_ODDLPARSER_EXPORT DataArrayList {
-    size_t         m_numItems;  ///< The number of items in the list.
-    Value         *m_dataList;  ///< The data list ( a Value ).
-    DataArrayList *m_next;      ///< The next data array list ( ddl_nullptr if last ).
-    Reference     *m_refs;
-    size_t         m_numRefs;
+    size_t m_numItems; ///< The number of items in the list.
+    Value *m_dataList; ///< The data list ( a Value ).
+    DataArrayList *m_next; ///< The next data array list ( ddl_nullptr if last ).
+    Reference *m_refs;
+    size_t m_numRefs;
 
     ///	@brief  The default constructor for initialization.
     DataArrayList();
@@ -221,13 +220,13 @@ struct DLL_ODDLPARSER_EXPORT DataArrayList {
     size_t size();
 
 private:
-    DataArrayList( const DataArrayList & ) ddl_no_copy;
-    DataArrayList &operator = ( const DataArrayList & ) ddl_no_copy;
+    DataArrayList(const DataArrayList &) ddl_no_copy;
+    DataArrayList &operator=(const DataArrayList &) ddl_no_copy;
 };
 
 ///	@brief  Stores the context of a parsed OpenDDL declaration.
 struct DLL_ODDLPARSER_EXPORT Context {
-    DDLNode *m_root;    ///< The root node of the OpenDDL node tree.
+    DDLNode *m_root; ///< The root node of the OpenDDL node tree.
 
     ///	@brief  Constructor for initialization.
     Context();
@@ -239,8 +238,8 @@ struct DLL_ODDLPARSER_EXPORT Context {
     void clear();
 
 private:
-    Context( const Context & ) ddl_no_copy;
-    Context &operator = ( const Context & ) ddl_no_copy;
+    Context(const Context &) ddl_no_copy;
+    Context &operator=(const Context &) ddl_no_copy;
 };
 
 END_ODDLPARSER_NS

+ 13 - 13
contrib/openddlparser/include/openddlparser/OpenDDLExport.h

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -40,7 +40,7 @@ class IOStreamBase;
 class DLL_ODDLPARSER_EXPORT OpenDDLExport {
 public:
     ///	@brief  The class constructor
-    OpenDDLExport( IOStreamBase *stream = ddl_nullptr );
+    OpenDDLExport(IOStreamBase *stream = nullptr);
 
     ///	@brief  The class destructor.
     ~OpenDDLExport();
@@ -49,29 +49,29 @@ public:
     /// @param  ctx         [in] Pointer to the context.
     /// @param  filename    [in] The filename for the export.
     /// @return True in case of success, false in case of an error.
-    bool exportContext( Context *ctx, const std::string &filename );
+    bool exportContext(Context *ctx, const std::string &filename);
 
     ///	@brief  Handles a node export.
     /// @param  node        [in] The node to handle with.
     /// @return True in case of success, false in case of an error.
-    bool handleNode( DDLNode *node );
+    bool handleNode(DDLNode *node);
 
     ///	@brief  Writes the statement to the stream.
     /// @param  statement   [in]  The content to write.
     /// @return True in case of success, false in case of an error.
-    bool writeToStream( const std::string &statement );
+    bool writeToStream(const std::string &statement);
 
 protected:
-    bool writeNode( DDLNode *node, std::string &statement );
-    bool writeNodeHeader( DDLNode *node, std::string &statement );
-    bool writeProperties( DDLNode *node, std::string &statement );
-    bool writeValueType( Value::ValueType type, size_t numItems, std::string &statement );
-    bool writeValue( Value *val, std::string &statement );
-    bool writeValueArray( DataArrayList *al, std::string &statement );
+    bool writeNode(DDLNode *node, std::string &statement);
+    bool writeNodeHeader(DDLNode *node, std::string &statement);
+    bool writeProperties(DDLNode *node, std::string &statement);
+    bool writeValueType(Value::ValueType type, size_t numItems, std::string &statement);
+    bool writeValue(Value *val, std::string &statement);
+    bool writeValueArray(DataArrayList *al, std::string &statement);
 
 private:
-    OpenDDLExport( const OpenDDLExport & ) ddl_no_copy;
-    OpenDDLExport &operator = ( const OpenDDLExport  & ) ddl_no_copy;
+    OpenDDLExport(const OpenDDLExport &) ddl_no_copy;
+    OpenDDLExport &operator=(const OpenDDLExport &) ddl_no_copy;
 
 private:
     IOStreamBase *m_stream;

+ 51 - 55
contrib/openddlparser/include/openddlparser/OpenDDLParser.h

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -22,13 +22,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 #pragma once
 
-#include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/OpenDDLParserUtils.h>
 #include <openddlparser/Value.h>
 
-#include <vector>
 #include <string>
+#include <vector>
 
 BEGIN_ODDLPARSER_NS
 
@@ -39,14 +39,9 @@ struct Identifier;
 struct Reference;
 struct Property;
 
-template<class T>
-inline
-bool isEmbeddedCommentOpenTag( T *in, T *end ) {
-    if ( in == end ) {
-        return false;
-    }
-
-    if ( in == '/' && in+1 == '*' ) {
+template <class T>
+inline bool isEmbeddedCommentOpenTag(T *in, T *end) {
+    if (in == '/' && in + 1 == '*') {
         return true;
     }
 
@@ -58,11 +53,10 @@ bool isEmbeddedCommentOpenTag( T *in, T *end ) {
 /// @param  end     [in] The end position in the buffer.
 ///	@return Pointer showing to the next token or the end of the buffer.
 ///	@detail Will not increase buffer when already a valid buffer was found.
-template<class T>
-inline
-T *lookForNextToken( T *in, T *end ) {
-    while( ( in != end ) && ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) ) {
-        in++;
+template <class T>
+inline T *lookForNextToken(T *in, T *end) {
+    while ((in != end) && (isSpace(*in) || isNewLine(*in) || ',' == *in)) {
+        ++in;
     }
     return in;
 }
@@ -72,26 +66,25 @@ T *lookForNextToken( T *in, T *end ) {
 /// @param  end     [in] The end position in the buffer.
 ///	@return Pointer showing to the next token or the end of the buffer.
 ///	@detail Will  increase buffer by a minimum of one.
-template<class T>
-inline
-T *getNextToken( T *in, T *end ) {
-    T *tmp( in );
-    in = lookForNextToken( in, end );
-    if( tmp == in ) {
-        in++;
+template <class T>
+inline T *getNextToken(T *in, T *end) {
+    T *tmp(in);
+    in = lookForNextToken(in, end);
+    if (tmp == in) {
+        ++in;
     }
     return in;
 }
 
 ///	@brief  Defines the log severity.
 enum LogSeverity {
-    ddl_debug_msg = 0,  ///< Debug message, for debugging
-    ddl_info_msg,       ///< Info messages, normal mode
-    ddl_warn_msg,       ///< Parser warnings
-    ddl_error_msg       ///< Parser errors
+    ddl_debug_msg = 0, ///< Debug message, for debugging
+    ddl_info_msg, ///< Info messages, normal mode
+    ddl_warn_msg, ///< Parser warnings
+    ddl_error_msg ///< Parser errors
 };
 
-DLL_ODDLPARSER_EXPORT const char *getTypeToken( Value::ValueType  type );
+DLL_ODDLPARSER_EXPORT const char *getTypeToken(Value::ValueType type);
 
 //-------------------------------------------------------------------------------------------------
 ///	@class		OpenDDLParser
@@ -105,7 +98,7 @@ DLL_ODDLPARSER_EXPORT const char *getTypeToken( Value::ValueType  type );
 class DLL_ODDLPARSER_EXPORT OpenDDLParser {
 public:
     ///	@brief  The log callback function pointer.
-    typedef void( *logCallback )( LogSeverity severity, const std::string &msg );
+    typedef void (*logCallback)(LogSeverity severity, const std::string &msg);
 
 public:
     ///	@brief  The default class constructor.
@@ -114,14 +107,14 @@ public:
     ///	@brief  The class constructor.
     ///	@param  buffer      [in] The buffer
     ///	@param  len         [in] Size of the buffer
-    OpenDDLParser( const char *buffer, size_t len );
+    OpenDDLParser(const char *buffer, size_t len);
 
     ///	@brief  The class destructor.
     ~OpenDDLParser();
 
     ///	@brief  Setter for an own log callback function.
     /// @param  callback    [in] The own callback.
-    void setLogCallback( logCallback callback );
+    void setLogCallback(logCallback callback);
 
     ///	@brief  Getter for the log callback.
     /// @return The current log callback.
@@ -130,11 +123,11 @@ public:
     ///	@brief  Assigns a new buffer to parse.
     ///	@param  buffer      [in] The buffer
     ///	@param  len         [in] Size of the buffer
-    void setBuffer( const char *buffer, size_t len );
+    void setBuffer(const char *buffer, size_t len);
 
     ///	@brief  Assigns a new buffer to parse.
     /// @param  buffer      [in] The buffer as a std::vector.
-    void setBuffer( const std::vector<char> &buffer );
+    void setBuffer(const std::vector<char> &buffer);
 
     ///	@brief  Returns the buffer pointer.
     /// @return The buffer pointer.
@@ -147,12 +140,15 @@ public:
     ///	@brief  Clears all parser data, including buffer and active context.
     void clear();
 
+    bool validate();
+
     ///	@brief  Starts the parsing of the OpenDDL-file.
     /// @return True in case of success, false in case of an error.
     /// @remark In case of errors check log.
     bool parse();
 
-    bool exportContext( Context *ctx, const std::string &filename );
+    
+    bool exportContext(Context *ctx, const std::string &filename);
 
     ///	@brief  Returns the root node.
     /// @return The root node.
@@ -163,37 +159,37 @@ public:
     Context *getContext() const;
 
 public: // parser helpers
-    char *parseNextNode( char *current, char *end );
-    char *parseHeader( char *in, char *end );
-    char *parseStructure( char *in, char *end );
-    char *parseStructureBody( char *in, char *end, bool &error );
-    void pushNode( DDLNode *node );
+    char *parseNextNode(char *current, char *end);
+    char *parseHeader(char *in, char *end);
+    char *parseStructure(char *in, char *end);
+    char *parseStructureBody(char *in, char *end, bool &error);
+    void pushNode(DDLNode *node);
     DDLNode *popNode();
     DDLNode *top();
-    static void normalizeBuffer( std::vector<char> &buffer );
-    static char *parseName( char *in, char *end, Name **name );
-    static char *parseIdentifier( char *in, char *end, Text **id );
-    static char *parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len );
-    static char *parseReference( char *in, char *end, std::vector<Name*> &names );
-    static char *parseBooleanLiteral( char *in, char *end, Value **boolean );
-    static char *parseIntegerLiteral( char *in, char *end, Value **integer, Value::ValueType integerType = Value::ddl_int32 );
-    static char *parseFloatingLiteral( char *in, char *end, Value **floating, Value::ValueType floatType= Value::ddl_float );
-    static char *parseStringLiteral( char *in, char *end, Value **stringData );
-    static char *parseHexaLiteral( char *in, char *end, Value **data );
-    static char *parseProperty( char *in, char *end, Property **prop );
-    static char *parseDataList( char *in, char *end, Value::ValueType type, Value **data, size_t &numValues, Reference **refs, size_t &numRefs );
-    static char *parseDataArrayList( char *in, char *end, Value::ValueType type, DataArrayList **dataList );
+    static void normalizeBuffer(std::vector<char> &buffer);
+    static char *parseName(char *in, char *end, Name **name);
+    static char *parseIdentifier(char *in, char *end, Text **id);
+    static char *parsePrimitiveDataType(char *in, char *end, Value::ValueType &type, size_t &len);
+    static char *parseReference(char *in, char *end, std::vector<Name *> &names);
+    static char *parseBooleanLiteral(char *in, char *end, Value **boolean);
+    static char *parseIntegerLiteral(char *in, char *end, Value **integer, Value::ValueType integerType = Value::ValueType::ddl_int32);
+    static char *parseFloatingLiteral(char *in, char *end, Value **floating, Value::ValueType floatType = Value::ValueType::ddl_float);
+    static char *parseStringLiteral(char *in, char *end, Value **stringData);
+    static char *parseHexaLiteral(char *in, char *end, Value **data);
+    static char *parseProperty(char *in, char *end, Property **prop);
+    static char *parseDataList(char *in, char *end, Value::ValueType type, Value **data, size_t &numValues, Reference **refs, size_t &numRefs);
+    static char *parseDataArrayList(char *in, char *end, Value::ValueType type, DataArrayList **dataList);
     static const char *getVersion();
 
 private:
-    OpenDDLParser( const OpenDDLParser & ) ddl_no_copy;
-    OpenDDLParser &operator = ( const OpenDDLParser & ) ddl_no_copy;
+    OpenDDLParser(const OpenDDLParser &) ddl_no_copy;
+    OpenDDLParser &operator=(const OpenDDLParser &) ddl_no_copy;
 
 private:
     logCallback m_logCallback;
     std::vector<char> m_buffer;
 
-    typedef std::vector<DDLNode*> DDLNodeStack;
+    typedef std::vector<DDLNode *> DDLNodeStack;
     DDLNodeStack m_stack;
     Context *m_context;
 };

+ 346 - 104
contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -26,64 +26,318 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 BEGIN_ODDLPARSER_NS
 
-template<class T>
-inline
-bool isUpperCase( T in ) {
-    return ( in >= 'A' && in <= 'Z' );
+template <class T>
+inline bool isUpperCase(T in) {
+    return (in >= 'A' && in <= 'Z');
 }
 
-template<class T>
-inline
-bool isLowerCase( T in ) {
-    return ( in >= 'a' && in <= 'z' );
+template <class T>
+inline bool isLowerCase(T in) {
+    return (in >= 'a' && in <= 'z');
 }
 
-template<class T>
-inline
-bool isSpace( const T in ) {
-    return ( ' ' == in || '\t' == in );
+template <class T>
+inline bool isSpace(const T in) {
+    return (' ' == in || '\t' == in);
 }
 
-template<class T>
-inline
-bool isNewLine( const T in ) {
-    return ( '\n' == in || ( '\r' == in ) );
+template <class T>
+inline bool isNewLine(const T in) {
+    return ('\n' == in || ('\r' == in));
 }
 
-template<class T>
-inline
-bool isSeparator( T in ) {
-    if( isSpace( in ) || ',' == in || '{' == in || '}' == in || '[' == in || '(' == in || ')' == in ) {
+template <class T>
+inline bool isSeparator(T in) {
+    if (isSpace(in) || ',' == in || '{' == in || '}' == in || '[' == in || '(' == in || ')' == in) {
         return true;
     }
     return false;
 }
 
-template<class T>
-inline
-bool isNumeric( const T in ) {
-    return ( in >= '0' && in <= '9' );
+static const unsigned char chartype_table[256] = {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 0-15
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 16-31
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 32-47
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    1,
+    0,
+    0,
+    0,
+    0,
+    0, // 48-63
+
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 64-79
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 80-95
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 96-111
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // 112-127
+
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0, // > 127
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+};
+
+template <class T>
+inline bool isNumeric(const T in) {
+    return (chartype_table[static_cast<size_t>(in)] == 1);
 }
 
-template<class T>
-inline
-bool isNotEndOfToken( T *in, T *end ) {
-    return ( '}' != *in && ',' != *in && !isSpace( *in ) && ')' != *in && in != end );
+template <class T>
+inline bool isNotEndOfToken(T *in, T *end) {
+    return ('}' != *in && ',' != *in && !isSpace(*in) && ')' != *in && in != end);
 }
 
-template<class T>
-inline
-bool isInteger( T *in, T *end ) {
-    if( in != end ) {
-        if( *in == '-' ) {
+template <class T>
+inline bool isInteger(T *in, T *end) {
+    if (in != end) {
+        if (*in == '-') {
             ++in;
         }
     }
 
-    bool result( false );
-    while( isNotEndOfToken( in, end ) ) {
-        result = isNumeric( *in );
-        if( !result ) {
+    bool result(false);
+    while (isNotEndOfToken(in, end)) {
+        result = isNumeric(*in);
+        if (!result) {
             break;
         }
         ++in;
@@ -92,40 +346,39 @@ bool isInteger( T *in, T *end ) {
     return result;
 }
 
-template<class T>
-inline
-bool isFloat( T *in, T *end ) {
-    if( in != end ) {
-        if( *in == '-' ) {
+template <class T>
+inline bool isFloat(T *in, T *end) {
+    if (in != end) {
+        if (*in == '-') {
             ++in;
         }
     }
 
     // check for <1>.0f
-    bool result( false );
-    while( isNotEndOfToken( in, end ) ) {
-        if( *in == '.' ) {
+    bool result(false);
+    while (isNotEndOfToken(in, end)) {
+        if (*in == '.') {
             result = true;
             break;
         }
-        result = isNumeric( *in );
-        if( !result ) {
+        result = isNumeric(*in);
+        if (!result) {
             return false;
         }
         ++in;
     }
 
     // check for 1<.>0f
-    if( *in == '.' ) {
+    if (*in == '.') {
         ++in;
     } else {
         return false;
     }
 
     // check for 1.<0>f
-    while( isNotEndOfToken( in, end ) ) {
-        result = isNumeric( *in );
-        if( !result ) {
+    while (isNotEndOfToken(in, end)) {
+        result = isNumeric(*in);
+        if (!result) {
             return false;
         }
         ++in;
@@ -134,24 +387,21 @@ bool isFloat( T *in, T *end ) {
     return result;
 }
 
-template<class T>
-inline
-bool isCharacter( const T in ) {
-    return ( ( in >= 'a' && in <= 'z' ) || ( in >= 'A' && in <= 'Z' ) );
+template <class T>
+inline bool isCharacter(const T in) {
+    return ((in >= 'a' && in <= 'z') || (in >= 'A' && in <= 'Z'));
 }
 
-template<class T>
-inline
-bool isStringLiteral( const T in ) {
-    return ( in == '\"' );
+template <class T>
+inline bool isStringLiteral(const T in) {
+    return (in == '\"');
 }
 
-template<class T>
-inline
-bool isHexLiteral( T *in, T *end ) {
-    if( *in == '0' ) {
-        if( in + 1 != end ) {
-            if( *( in + 1 ) == 'x' || *( in + 1 ) == 'X' ) {
+template <class T>
+inline bool isHexLiteral(T *in, T *end) {
+    if (*in == '0') {
+        if (in + 1 != end) {
+            if (*(in + 1) == 'x' || *(in + 1) == 'X') {
                 return true;
             }
         }
@@ -160,13 +410,12 @@ bool isHexLiteral( T *in, T *end ) {
     return false;
 }
 
-template<class T>
-inline
-bool isReference( T *in, T *end ) {
-    if( *in == 'r' ) {
-        if( *(in+1) == 'e' ) {
-            if( *(in+2) == 'f' ) {
-                if( ( in + 2 ) != end ) {
+template <class T>
+inline bool isReference(T *in, T *end) {
+    if (*in == 'r') {
+        if (*(in + 1) == 'e') {
+            if (*(in + 2) == 'f') {
+                if ((in + 2) != end) {
                     return true;
                 }
             }
@@ -176,16 +425,14 @@ bool isReference( T *in, T *end ) {
     return false;
 }
 
-template<class T>
-inline
-bool isEndofLine( const T in ) {
-    return ( '\n' == in );
+template <class T>
+inline bool isEndofLine(const T in) {
+    return ('\n' == in);
 }
 
-template<class T>
-inline
-static T *getNextSeparator( T *in, T *end ) {
-    while( !isSeparator( *in ) || in == end ) {
+template <class T>
+inline static T *getNextSeparator(T *in, T *end) {
+    while (!isSeparator(*in) || in == end) {
         ++in;
     }
     return in;
@@ -193,30 +440,28 @@ static T *getNextSeparator( T *in, T *end ) {
 
 static const int ErrorHex2Decimal = 9999999;
 
-inline
-int hex2Decimal( char in ) {
-    if( isNumeric( in ) ) {
-        return ( in - 48 );
+inline int hex2Decimal(char in) {
+    if (isNumeric(in)) {
+        return (in - 48);
     }
 
-    char hexCodeLower( 'a' ), hexCodeUpper( 'A' );
-    for( int i = 0; i<16; i++ ) {
-        if( in == hexCodeLower + i || in == hexCodeUpper + i ) {
-            return ( i+10 );
+    char hexCodeLower('a'), hexCodeUpper('A');
+    for (int i = 0; i < 16; i++) {
+        if (in == hexCodeLower + i || in == hexCodeUpper + i) {
+            return (i + 10);
         }
     }
 
     return ErrorHex2Decimal;
 }
 
-template<class T>
-inline
-bool isComment( T *in, T *end ) {
-    if ( *in=='/' ) {
-        if ( in+1!=end ) {
-            if ( *( in+1 )=='/' ) {
-                char *drive( ( in+2 ) );
-                if ( (isUpperCase<T>( *drive )||isLowerCase<T>( *drive ))&&*( drive+1 )=='/' )  {
+template <class T>
+inline bool isComment(T *in, T *end) {
+    if (*in == '/') {
+        if (in + 1 != end) {
+            if (*(in + 1) == '/') {
+                char *drive((in + 2));
+                if ((isUpperCase<T>(*drive) || isLowerCase<T>(*drive)) && *(drive + 1) == '/') {
                     return false;
                 } else {
                     return true;
@@ -228,9 +473,8 @@ bool isComment( T *in, T *end ) {
     return false;
 }
 
-template<class T>
-inline
-bool isCommentOpenTag(T *in, T *end ) {
+template <class T>
+inline bool isCommentOpenTag(T *in, T *end) {
     if (*in == '/') {
         if (in + 1 != end) {
             if (*(in + 1) == '*') {
@@ -242,9 +486,8 @@ bool isCommentOpenTag(T *in, T *end ) {
     return false;
 }
 
-template<class T>
-inline
-bool isCommentCloseTag(T *in, T *end) {
+template <class T>
+inline bool isCommentCloseTag(T *in, T *end) {
     if (*in == '*') {
         if (in + 1 != end) {
             if (*(in + 1) == '/') {
@@ -257,4 +500,3 @@ bool isCommentCloseTag(T *in, T *end) {
 }
 
 END_ODDLPARSER_NS
-

+ 4 - 4
contrib/openddlparser/include/openddlparser/OpenDDLStream.h

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -38,7 +38,7 @@ public:
     /// @brief  The class destructor, virtual.
     virtual ~StreamFormatterBase();
 
-    /// @brief  Will format the sring and return the new formatted result.
+    /// @brief  Will format the string 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);
@@ -52,7 +52,7 @@ 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);
+    explicit IOStreamBase(StreamFormatterBase *formatter = nullptr);
 
     /// @brief  The class destructor, virtual.
     virtual ~IOStreamBase();
@@ -74,7 +74,7 @@ public:
     /// @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 );
+    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.

+ 226 - 0
contrib/openddlparser/include/openddlparser/TPoolAllocator.h

@@ -0,0 +1,226 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2019 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>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+//-------------------------------------------------------------------------------------------------
+///	@class		TPoolAllocator
+///	@ingroup	CPPCore
+///
+///	@brief  This class implements a simple pool-based allocation scheme.
+/// Initially you have to define its size. Each allocation will be done from this initially created
+/// pool. You have to release all pooled instances after the usage.
+/// This allocation scheme is fast and does no call any new-calls during the lifetime of the
+/// allocator.
+//-------------------------------------------------------------------------------------------------
+template <class T>
+class TPoolAllocator {
+public:
+    TPoolAllocator();
+    TPoolAllocator(size_t numItems);
+    ~TPoolAllocator();
+    T *alloc();
+    void release();
+    void reserve(size_t size);
+    void clear();
+    size_t capacity() const;
+    size_t reservedMem() const;
+    size_t freeMem() const;
+    void dumpAllocations(std::string &allocs);
+    void resize(size_t growSize);
+
+    CPPCORE_NONE_COPYING(TPoolAllocator)
+
+private:
+    struct Pool {
+        size_t m_poolsize;
+        T *m_pool;
+        size_t m_currentIdx;
+        Pool *m_next;
+
+        Pool() :
+                m_poolsize(0u), m_pool(nullptr), m_currentIdx(0u), m_next(nullptr) {
+            // empty
+        }
+
+        Pool(size_t numItems, Pool *prev) :
+                m_poolsize(numItems), m_pool(nullptr), m_currentIdx(0u), m_next(prev) {
+            m_pool = new T[m_poolsize];
+        }
+
+        ~Pool() {
+            delete[] m_pool;
+            m_pool = nullptr;
+        }
+
+        CPPCORE_NONE_COPYING(Pool)
+    };
+
+    Pool *getFreePool() {
+        Pool *current(m_freeList);
+        if (nullptr != m_freeList) {
+            m_freeList = m_freeList->m_next;
+        }
+        return current;
+    }
+
+    Pool *m_first;
+    Pool *m_current;
+    Pool *m_freeList;
+    size_t m_capacity;
+};
+
+template <class T>
+inline TPoolAllocator<T>::TPoolAllocator() :
+        m_first(nullptr), m_current(nullptr), m_freeList(nullptr), m_capacity(0L) {
+    // empty
+}
+
+template <class T>
+inline TPoolAllocator<T>::TPoolAllocator(size_t numItems) :
+        m_first(nullptr), m_current(nullptr), m_freeList(nullptr), m_capacity(0L) {
+    m_first = new Pool(numItems);
+    m_capacity += numItems;
+    m_current = m_first;
+}
+
+template <class T>
+inline TPoolAllocator<T>::~TPoolAllocator() {
+    clear();
+}
+
+template <class T>
+inline T *TPoolAllocator<T>::alloc() {
+    if (nullptr == m_current) {
+        return nullptr;
+    }
+
+    if (m_current->m_currentIdx == m_current->m_poolsize) {
+        resize(m_current->m_poolsize);
+    }
+
+    T *ptr(&m_current->m_pool[m_current->m_currentIdx]);
+    m_current->m_currentIdx++;
+
+    return ptr;
+}
+
+template <class T>
+inline void TPoolAllocator<T>::release() {
+    if (nullptr == m_current) {
+        return;
+    }
+
+    Pool *current(m_first);
+    while (nullptr != current) {
+        current->m_currentIdx = 0;
+        current = current->m_next;
+    }
+    m_freeList = m_first->m_next;
+    m_current = m_first;
+}
+
+template <class T>
+inline void TPoolAllocator<T>::reserve(size_t size) {
+    clear();
+
+    m_first = new Pool(size, nullptr);
+    m_current = m_first;
+
+    m_current->m_pool = new T[size];
+    m_current->m_poolsize = size;
+
+    m_capacity = size;
+}
+
+template <class T>
+inline void TPoolAllocator<T>::clear() {
+    if (nullptr == m_current) {
+        return;
+    }
+
+    Pool *next(m_first);
+    while (nullptr != next) {
+        Pool *current = next;
+        next = current->m_next;
+        delete current;
+    }
+    m_current = nullptr;
+    m_freeList = nullptr;
+}
+
+template <class T>
+inline size_t TPoolAllocator<T>::capacity() const {
+    return m_capacity;
+}
+
+template <class T>
+inline size_t TPoolAllocator<T>::reservedMem() const {
+    return m_capacity * sizeof(T);
+}
+
+template <class T>
+inline size_t TPoolAllocator<T>::freeMem() const {
+    if (nullptr == m_current) {
+        return 0L;
+    }
+
+    return (m_current->m_poolsize - m_current->m_currentIdx);
+}
+
+template <class T>
+inline void TPoolAllocator<T>::dumpAllocations(std::string &allocs) {
+    allocs.clear();
+    allocs += "Number allocations = ";
+    allocs += std::to_string(m_current->m_currentIdx);
+    allocs += "\n";
+}
+
+template <class T>
+inline void TPoolAllocator<T>::resize(size_t growSize) {
+    if (nullptr != m_current) {
+        if (growSize < m_current->m_poolsize) {
+            return;
+        }
+    }
+
+    if (nullptr == m_first) {
+        m_first = new Pool(growSize, nullptr);
+        m_current = m_first;
+        m_capacity += m_current->m_poolsize;
+    } else {
+        Pool *pool = getFreePool();
+        if (nullptr == pool) {
+            pool = new Pool(growSize, nullptr);
+            m_capacity += growSize;
+        }
+        m_current->m_next = pool;
+        m_current = m_current->m_next;
+    }
+}
+
+END_ODDLPARSER_NS

+ 2 - 2
contrib/openddlparser/include/openddlparser/Value.h

@@ -1,7 +1,7 @@
 /*-----------------------------------------------------------------------------------------------
 The MIT License (MIT)
 
-Copyright (c) 2014-2015 Kim Kulling
+Copyright (c) 2014-2020 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
@@ -101,7 +101,7 @@ public:
     };
 
     ///	@brief  This enum describes the data type stored in the value.
-    enum ValueType {
+    enum class ValueType {
         ddl_none = -1,          ///< Nothing specified
         ddl_bool = 0,           ///< A boolean type
         ddl_int8,               ///< Integer type, 8 bytes

+ 50 - 51
include/assimp/StringUtils.h

@@ -44,22 +44,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_STRINGUTILS_H
 
 #ifdef __GNUC__
-#   pragma GCC system_header
+#pragma GCC system_header
 #endif
 
 #include <assimp/defs.h>
 
-#include <sstream>
 #include <stdarg.h>
-#include <cstdlib>
-#include <algorithm> 
+#include <algorithm>
 #include <cctype>
+#include <cstdlib>
 #include <locale>
+#include <sstream>
 
 #ifdef _MSC_VER
-#   define AI_SIZEFMT "%Iu"
+#define AI_SIZEFMT "%Iu"
 #else
-#   define AI_SIZEFMT "%zu"
+#define AI_SIZEFMT "%zu"
 #endif
 
 ///	@fn		ai_snprintf
@@ -71,35 +71,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ///	@return	The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned.
 #if defined(_MSC_VER) && _MSC_VER < 1900
 
-    AI_FORCE_INLINE
-    int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
-		int count(-1);
-		if (0 != size) {
-			count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
-		}
-		if (count == -1) {
-			count = _vscprintf(format, ap);
-		}
+AI_FORCE_INLINE
+int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
+    int count(-1);
+    if (0 != size) {
+        count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+    }
+    if (count == -1) {
+        count = _vscprintf(format, ap);
+    }
 
-		return count;
-	}
+    return count;
+}
 
-    AI_FORCE_INLINE
-    int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
-		int count;
-		va_list ap;
+AI_FORCE_INLINE
+int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
+    int count;
+    va_list ap;
 
-		va_start(ap, format);
-		count = c99_ai_vsnprintf(outBuf, size, format, ap);
-		va_end(ap);
+    va_start(ap, format);
+    count = c99_ai_vsnprintf(outBuf, size, format, ap);
+    va_end(ap);
 
-		return count;
-	}
+    return count;
+}
 
 #elif defined(__MINGW32__)
-#   define ai_snprintf __mingw_snprintf
+#define ai_snprintf __mingw_snprintf
 #else
-#   define ai_snprintf snprintf
+#define ai_snprintf snprintf
 #endif
 
 ///	@fn		to_string
@@ -107,8 +107,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ///	@param	value   The value to write into the std::string.
 ///	@return	The value as a std::string
 template <typename T>
-AI_FORCE_INLINE
-std::string to_string( T value ) {
+AI_FORCE_INLINE std::string to_string(T value) {
     std::ostringstream os;
     os << value;
 
@@ -121,17 +120,17 @@ std::string to_string( T value ) {
 /// @param  end     The last character
 ///	@return	The float value, 0.0f in cas of an error.
 AI_FORCE_INLINE
-float ai_strtof( const char *begin, const char *end ) {
-    if ( nullptr == begin ) {
+float ai_strtof(const char *begin, const char *end) {
+    if (nullptr == begin) {
         return 0.0f;
     }
-    float val( 0.0f );
-    if ( nullptr == end ) {
-        val = static_cast< float >( ::atof( begin ) );
+    float val(0.0f);
+    if (nullptr == end) {
+        val = static_cast<float>(::atof(begin));
     } else {
-        std::string::size_type len( end - begin );
-        std::string token( begin, len );
-        val = static_cast< float >( ::atof( token.c_str() ) );
+        std::string::size_type len(end - begin);
+        std::string token(begin, len);
+        val = static_cast<float>(::atof(token.c_str()));
     }
 
     return val;
@@ -141,16 +140,15 @@ float ai_strtof( const char *begin, const char *end ) {
 ///	@brief	The portable to convert a decimal value into a hexadecimal string.
 ///	@param	toConvert   Value to convert
 ///	@return	The hexadecimal string, is empty in case of an error.
-template<class T>
-AI_FORCE_INLINE
-std::string DecimalToHexa( T toConvert ) {
+template <class T>
+AI_FORCE_INLINE std::string DecimalToHexa(T toConvert) {
     std::string result;
     std::stringstream ss;
     ss << std::hex << toConvert;
     ss >> result;
 
-    for ( size_t i = 0; i < result.size(); ++i ) {
-        result[ i ] = (char) toupper( result[ i ] );
+    for (size_t i = 0; i < result.size(); ++i) {
+        result[i] = (char)toupper(result[i]);
     }
 
     return result;
@@ -164,31 +162,32 @@ std::string DecimalToHexa( T toConvert ) {
 ///	@param	with_head   #
 ///	@return	The hexadecimal string, is empty in case of an error.
 AI_FORCE_INLINE std::string Rgba2Hex(int r, int g, int b, int a, bool with_head) {
-	std::stringstream ss;
-	if (with_head) {
-		ss << "#";
+    std::stringstream ss;
+    if (with_head) {
+        ss << "#";
     }
-	ss << std::hex << (r << 24 | g << 16 | b << 8 | a);
+    ss << std::hex << (r << 24 | g << 16 | b << 8 | a);
 
     return ss.str();
 }
 
 // trim from start (in place)
-inline void ltrim(std::string &s) {
+AI_FORCE_INLINE void ltrim(std::string &s) {
     s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
         return !std::isspace(ch);
     }));
 }
 
 // trim from end (in place)
-inline void rtrim(std::string &s) {
+AI_FORCE_INLINE void rtrim(std::string &s) {
     s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
         return !std::isspace(ch);
-    }).base(), s.end());
+    }).base(),
+            s.end());
 }
 
 // trim from both ends (in place)
-inline void trim(std::string &s) {
+AI_FORCE_INLINE void trim(std::string &s) {
     ltrim(s);
     rtrim(s);
 }

+ 11 - 1
include/assimp/XmlParser.h

@@ -179,7 +179,7 @@ public:
         return true;
     }
 
-    static inline bool getFloatAttribute( XmlNode &xmlNode, const char *name, float &val ) {
+    static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val ) {
         pugi::xml_attribute attr = xmlNode.attribute(name);
         if (attr.empty()) {
             return false;
@@ -190,6 +190,16 @@ public:
 
     }
 
+    static inline bool getDoubleAttribute( XmlNode &xmlNode, const char *name, double &val ) {
+        pugi::xml_attribute attr = xmlNode.attribute(name);
+        if (attr.empty()) {
+            return false;
+        }
+
+        val = attr.as_double();
+        return true;
+    }
+
     static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) {
         pugi::xml_attribute attr = xmlNode.attribute(name);
         if (attr.empty()) {

+ 19 - 12
include/assimp/fast_atof.h

@@ -24,11 +24,11 @@
 #include <cmath>
 #include <limits>
 #include <stdint.h>
-#include <stdexcept>
 #include <assimp/defs.h>
 
 #include "StringComparison.h"
 #include <assimp/DefaultLogger.hpp>
+#include <assimp/Exceptional.h>
 
 #ifdef _MSC_VER
 #  include <stdint.h>
@@ -185,13 +185,15 @@ unsigned int strtoul_cppstyle( const char* in, const char** out=0) {
 // Special version of the function, providing higher accuracy and safety
 // It is mainly used by fast_atof to prevent ugly and unwanted integer overflows.
 // ------------------------------------------------------------------------------------
+template<typename ExceptionType = DeadlyImportError>
 inline
 uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) {
     unsigned int cur = 0;
     uint64_t value = 0;
 
     if ( *in < '0' || *in > '9' ) {
-        throw std::invalid_argument( std::string( "The string \"" ) + in + "\" cannot be converted into a value." );
+        // The string is known to be bad, so don't risk printing the whole thing.
+        throw ExceptionType("The string \"", std::string(in).substr(0, 100), "\" cannot be converted into a value." );
     }
 
     for ( ;; ) {
@@ -237,6 +239,7 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino
 // ------------------------------------------------------------------------------------
 // signed variant of strtoul10_64
 // ------------------------------------------------------------------------------------
+template<typename ExceptionType = DeadlyImportError>
 inline
 int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) {
     bool inv = (*in == '-');
@@ -244,7 +247,7 @@ int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inou
         ++in;
     }
 
-    int64_t value = strtoul10_64(in, out, max_inout);
+    int64_t value = strtoul10_64<ExceptionType>(in, out, max_inout);
     if (inv) {
         value = -value;
     }
@@ -259,7 +262,7 @@ int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inou
 //! about 6 times faster than atof in win32.
 // If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
 // ------------------------------------------------------------------------------------
-template<typename Real>
+template<typename Real, typename ExceptionType = DeadlyImportError>
 inline
 const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) {
     Real f = 0;
@@ -289,13 +292,14 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
 
     if (!(c[0] >= '0' && c[0] <= '9') &&
             !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) {
-        throw std::invalid_argument("Cannot parse string "
-                                    "as real number: does not start with digit "
+        // The string is known to be bad, so don't risk printing the whole thing.
+        throw ExceptionType("Cannot parse string \"", std::string(c).substr(0, 100), 
+                                    "\" as a real number: does not start with digit "
                                     "or decimal point followed by digit.");
     }
 
     if (*c != '.' && (! check_comma || c[0] != ',')) {
-        f = static_cast<Real>( strtoul10_64 ( c, &c) );
+        f = static_cast<Real>( strtoul10_64<ExceptionType> ( c, &c) );
     }
 
     if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') {
@@ -310,7 +314,7 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
         // number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between
         // 1 and 15.
         unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS;
-        double pl = static_cast<double>( strtoul10_64 ( c, &c, &diff ));
+        double pl = static_cast<double>( strtoul10_64<ExceptionType> ( c, &c, &diff ));
 
         pl *= fast_atof_table[diff];
         f += static_cast<Real>( pl );
@@ -332,7 +336,7 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
         // The reason float constants are used here is that we've seen cases where compilers
         // would perform such casts on compile-time constants at runtime, which would be
         // bad considering how frequently fast_atoreal_move<float> is called in Assimp.
-        Real exp = static_cast<Real>( strtoul10_64(c, &c) );
+        Real exp = static_cast<Real>( strtoul10_64<ExceptionType>(c, &c) );
         if (einv) {
             exp = -exp;
         }
@@ -348,26 +352,29 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
 
 // ------------------------------------------------------------------------------------
 // The same but more human.
+template<typename ExceptionType = DeadlyImportError>
 inline
 ai_real fast_atof(const char* c) {
     ai_real ret(0.0);
-    fast_atoreal_move<ai_real>(c, ret);
+    fast_atoreal_move<ai_real, ExceptionType>(c, ret);
 
     return ret;
 }
 
+template<typename ExceptionType = DeadlyImportError>
 inline
 ai_real fast_atof( const char* c, const char** cout) {
     ai_real ret(0.0);
-    *cout = fast_atoreal_move<ai_real>(c, ret);
+    *cout = fast_atoreal_move<ai_real, ExceptionType>(c, ret);
 
     return ret;
 }
 
+template<typename ExceptionType = DeadlyImportError>
 inline
 ai_real fast_atof( const char** inout) {
     ai_real ret(0.0);
-    *inout = fast_atoreal_move<ai_real>(*inout, ret);
+    *inout = fast_atoreal_move<ai_real, ExceptionType>(*inout, ret);
 
     return ret;
 }

+ 1 - 1
test/unit/utOpenGEXImportExport.cpp

@@ -48,7 +48,7 @@ using namespace Assimp;
 
 class utOpenGEXImportExport : public AbstractImportExportBase {
 public:
-    virtual bool importerTest() {
+    bool importerTest() override {
         Assimp::Importer importer;
         const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OpenGEX/Example.ogex", 0);
         return nullptr != scene;

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott