Browse Source

Merge branch 'master' of https://github.com/assimp/assimp into implementation_warning_fix

# Conflicts:
#	code/AMFImporter_Postprocess.cpp
#	code/FBXConverter.cpp
#	code/IFCLoader.cpp
#	code/NDOLoader.cpp
#	code/glTFAsset.inl
Jared Mulconry 8 years ago
parent
commit
f206249fbf

+ 10 - 0
.travis.yml

@@ -1,5 +1,6 @@
 before_install:
 before_install:
   - sudo apt-get update -qq
   - sudo apt-get update -qq
+  - sudo apt-get install cmake
   - sudo apt-get install cmake python3
   - sudo apt-get install cmake python3
   - if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
   - if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
   - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
   - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
@@ -18,6 +19,7 @@ branches:
 
 
 env:
 env:
   global:
   global:
+    - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
     - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
     - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
   matrix:
   matrix:
     - LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON
     - LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON
@@ -52,3 +54,11 @@ after_success:
   - lcov --list coverage.info
   - lcov --list coverage.info
   - coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info
   - coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info
 
 
+addons:
+  coverity_scan:
+    project:
+      name: "assimp/assimp"
+    notification_email: [email protected]
+    build_command_prepend: "cmake"
+    build_command: "make"
+    branch_pattern: coverity_scan

+ 1 - 0
appveyor.yml

@@ -40,3 +40,4 @@ after_build:
 artifacts:
 artifacts:
   - path: assimp.7z
   - path: assimp.7z
     name: assimp_lib
     name: assimp_lib
+

+ 8 - 12
code/AMFImporter_Postprocess.cpp

@@ -336,25 +336,21 @@ auto texmap_is_equal = [](const CAMFImporter_NodeElement_TexMap* pTexMap1, const
 	} while(pInputList.size() > 0);
 	} while(pInputList.size() > 0);
 }
 }
 
 
-void AMFImporter::Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& pMetadataList, aiNode& pSceneNode) const
+void AMFImporter::Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& metadataList, aiNode& sceneNode) const
 {
 {
-	if(pMetadataList.size() > 0)
+	if ( !metadataList.empty() )
 	{
 	{
-		if(pSceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
+		if(sceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
 
 
 		// copy collected metadata to output node.
 		// copy collected metadata to output node.
-		pSceneNode.mMetaData = new aiMetadata();
-		pSceneNode.mMetaData->mNumProperties = static_cast<unsigned int>(pMetadataList.size());
-		pSceneNode.mMetaData->mKeys = new aiString[pSceneNode.mMetaData->mNumProperties];
-		pSceneNode.mMetaData->mValues = new aiMetadataEntry[pSceneNode.mMetaData->mNumProperties];
+        sceneNode.mMetaData = aiMetadata::Alloc( static_cast<unsigned int>(metadataList.size()) );
+		size_t meta_idx( 0 );
 
 
-		size_t meta_idx = 0;
-
-		for(const CAMFImporter_NodeElement_Metadata& metadata: pMetadataList)
+		for(const CAMFImporter_NodeElement_Metadata& metadata: metadataList)
 		{
 		{
-			pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata.Type, metadata.Value.c_str());
+			sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata.Type, aiString(metadata.Value));
 		}
 		}
-	}// if(pMetadataList.size() > 0)
+	}// if(!metadataList.empty())
 }
 }
 
 
 void AMFImporter::Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode)
 void AMFImporter::Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode)

+ 19 - 17
code/BaseImporter.cpp

@@ -56,7 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <sstream>
 #include <sstream>
 #include <cctype>
 #include <cctype>
 
 
-
 using namespace Assimp;
 using namespace Assimp;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -461,29 +460,32 @@ void BaseImporter::TextFileToBuffer(IOStream* stream,
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-namespace Assimp
-{
+namespace Assimp {
     // Represents an import request
     // Represents an import request
-    struct LoadRequest
-    {
+    struct LoadRequest {
         LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
         LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
-            : file(_file), flags(_flags), refCnt(1),scene(NULL), loaded(false), id(_id)
-        {
-            if (_map)
+        : file(_file)
+        , flags(_flags)
+        , refCnt(1)
+        , scene(NULL)
+        , loaded(false)
+        , id(_id) {
+            if ( _map ) {
                 map = *_map;
                 map = *_map;
+            }
         }
         }
 
 
-        const std::string file;
-        unsigned int flags;
-        unsigned int refCnt;
-        aiScene* scene;
-        bool loaded;
-        BatchLoader::PropertyMap map;
-        unsigned int id;
-
-        bool operator== (const std::string& f) const {
+        bool operator== ( const std::string& f ) const {
             return file == f;
             return file == f;
         }
         }
+
+        const std::string        file;
+        unsigned int             flags;
+        unsigned int             refCnt;
+        aiScene                 *scene;
+        bool                     loaded;
+        BatchLoader::PropertyMap map;
+        unsigned int             id;
     };
     };
 }
 }
 
 

+ 10 - 8
code/BlenderLoader.cpp

@@ -106,6 +106,8 @@ BlenderImporter::~BlenderImporter()
     delete modifier_cache;
     delete modifier_cache;
 }
 }
 
 
+static const char* Tokens[] = { "BLENDER" };
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
 bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
@@ -117,8 +119,7 @@ bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, b
 
 
     else if ((!extension.length() || checkSig) && pIOHandler)   {
     else if ((!extension.length() || checkSig) && pIOHandler)   {
         // note: this won't catch compressed files
         // note: this won't catch compressed files
-        const char* tokens[] = {"BLENDER"};
-        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+        return SearchFileHeaderForToken(pIOHandler,pFile, Tokens,1);
     }
     }
     return false;
     return false;
 }
 }
@@ -172,7 +173,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
 
 
     char magic[8] = {0};
     char magic[8] = {0};
     stream->Read(magic,7,1);
     stream->Read(magic,7,1);
-    if (strcmp(magic,"BLENDER")) {
+    if (strcmp(magic, Tokens[0] )) {
         // Check for presence of the gzip header. If yes, assume it is a
         // Check for presence of the gzip header. If yes, assume it is a
         // compressed blend file and try uncompressing it, else fail. This is to
         // compressed blend file and try uncompressing it, else fail. This is to
         // avoid uncompressing random files which our loader might end up with.
         // avoid uncompressing random files which our loader might end up with.
@@ -347,8 +348,9 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD
         if (cur->object) {
         if (cur->object) {
             if(!cur->object->parent) {
             if(!cur->object->parent) {
                 no_parents.push_back(cur->object.get());
                 no_parents.push_back(cur->object.get());
+            } else {
+                conv.objects.insert( cur->object.get() );
             }
             }
-            else conv.objects.insert(cur->object.get());
         }
         }
     }
     }
     for (std::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
     for (std::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
@@ -431,8 +433,9 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
         // so we can extract the file extension from it.
         // so we can extract the file extension from it.
         const size_t nlen = strlen( img->name );
         const size_t nlen = strlen( img->name );
         const char* s = img->name+nlen, *e = s;
         const char* s = img->name+nlen, *e = s;
-
-        while (s >= img->name && *s != '.')--s;
+        while ( s >= img->name && *s != '.' ) {
+            --s;
+        }
 
 
         tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
         tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
         tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
         tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
@@ -449,8 +452,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
         tex->pcData = reinterpret_cast<aiTexel*>(ch);
         tex->pcData = reinterpret_cast<aiTexel*>(ch);
 
 
         LogInfo("Reading embedded texture, original file was "+std::string(img->name));
         LogInfo("Reading embedded texture, original file was "+std::string(img->name));
-    }
-    else {
+    } else {
         name = aiString( img->name );
         name = aiString( img->name );
     }
     }
 
 

+ 1 - 1
code/BlenderScene.cpp

@@ -805,5 +805,5 @@ void DNA::RegisterConverters() {
     converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
     converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
 }
 }
 
 
-
 #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
 #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
+

+ 11 - 14
code/FBXConverter.cpp

@@ -1075,10 +1075,7 @@ void Converter::SetupNodeMetadata( const Model& model, aiNode& nd )
 
 
     // create metadata on node
     // create metadata on node
     std::size_t numStaticMetaData = 2;
     std::size_t numStaticMetaData = 2;
-    aiMetadata* data = new aiMetadata();
-    data->mNumProperties = static_cast<unsigned int>(unparsedProperties.size() + numStaticMetaData);
-    data->mKeys = new aiString[ data->mNumProperties ]();
-    data->mValues = new aiMetadataEntry[ data->mNumProperties ]();
+    aiMetadata* data = aiMetadata::Alloc( static_cast<unsigned int>(unparsedProperties.size() + numStaticMetaData) );
     nd.mMetaData = data;
     nd.mMetaData = data;
     int index = 0;
     int index = 0;
 
 
@@ -1089,22 +1086,22 @@ void Converter::SetupNodeMetadata( const Model& model, aiNode& nd )
 
 
     // add unparsed properties to the node's metadata
     // add unparsed properties to the node's metadata
     for( const DirectPropertyMap::value_type& prop : unparsedProperties ) {
     for( const DirectPropertyMap::value_type& prop : unparsedProperties ) {
-
         // Interpret the property as a concrete type
         // Interpret the property as a concrete type
-        if ( const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >() )
+        if ( const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >() ) {
             data->Set( index++, prop.first, interpreted->Value() );
             data->Set( index++, prop.first, interpreted->Value() );
-        else if ( const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >() )
+        } else if ( const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >() ) {
             data->Set( index++, prop.first, interpreted->Value() );
             data->Set( index++, prop.first, interpreted->Value() );
-        else if ( const TypedProperty<uint64_t>* interpreted = prop.second->As<TypedProperty<uint64_t> >() )
+        } else if ( const TypedProperty<uint64_t>* interpreted = prop.second->As<TypedProperty<uint64_t> >() ) {
             data->Set( index++, prop.first, interpreted->Value() );
             data->Set( index++, prop.first, interpreted->Value() );
-        else if ( const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >() )
+        } else if ( const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >() ) {
             data->Set( index++, prop.first, interpreted->Value() );
             data->Set( index++, prop.first, interpreted->Value() );
-        else if ( const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >() )
+        } else if ( const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >() ) {
             data->Set( index++, prop.first, aiString( interpreted->Value() ) );
             data->Set( index++, prop.first, aiString( interpreted->Value() ) );
-        else if ( const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >() )
+        } else if ( const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >() ) {
             data->Set( index++, prop.first, interpreted->Value() );
             data->Set( index++, prop.first, interpreted->Value() );
-        else
-            assert( false );
+        } else {
+            ai_assert( false );
+        }
     }
     }
 }
 }
 
 
@@ -1394,9 +1391,9 @@ unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, cons
     // allocate tangents, binormals.
     // allocate tangents, binormals.
     const std::vector<aiVector3D>& tangents = mesh.GetTangents();
     const std::vector<aiVector3D>& tangents = mesh.GetTangents();
     const std::vector<aiVector3D>* binormals = &mesh.GetBinormals();
     const std::vector<aiVector3D>* binormals = &mesh.GetBinormals();
+    std::vector<aiVector3D> tempBinormals;
 
 
     if ( tangents.size() ) {
     if ( tangents.size() ) {
-        std::vector<aiVector3D> tempBinormals;
         if ( !binormals->size() ) {
         if ( !binormals->size() ) {
             if ( normals.size() ) {
             if ( normals.size() ) {
                 // XXX this computes the binormals for the entire mesh, not only
                 // XXX this computes the binormals for the entire mesh, not only

+ 8 - 5
code/HMPLoader.cpp

@@ -127,8 +127,7 @@ void HMPImporter::InternReadFile( const std::string& pFile,
         throw DeadlyImportError( "HMP File is too small.");
         throw DeadlyImportError( "HMP File is too small.");
 
 
     // Allocate storage and copy the contents of the file to a memory buffer
     // Allocate storage and copy the contents of the file to a memory buffer
-    std::vector<uint8_t> buffer(fileSize);
-    mBuffer = &buffer[0];
+    mBuffer = new uint8_t[fileSize];
     file->Read( (void*)mBuffer, 1, fileSize);
     file->Read( (void*)mBuffer, 1, fileSize);
     iFileSize = (unsigned int)fileSize;
     iFileSize = (unsigned int)fileSize;
 
 
@@ -174,7 +173,9 @@ void HMPImporter::InternReadFile( const std::string& pFile,
     // Set the AI_SCENE_FLAGS_TERRAIN bit
     // Set the AI_SCENE_FLAGS_TERRAIN bit
     pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
     pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
 
 
-    // File buffer destructs automatically now
+    delete[] mBuffer;
+    mBuffer= nullptr;
+
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -449,11 +450,13 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szC
 
 
     // read the type of the skin ...
     // read the type of the skin ...
     // sometimes we need to skip 12 bytes here, I don't know why ...
     // sometimes we need to skip 12 bytes here, I don't know why ...
-    uint32_t iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
+    uint32_t iType = *((uint32_t*)szCursor);
+    szCursor += sizeof(uint32_t);
     if (0 == iType)
     if (0 == iType)
     {
     {
         szCursor += sizeof(uint32_t) * 2;
         szCursor += sizeof(uint32_t) * 2;
-        iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
+        iType = *((uint32_t*)szCursor);
+        szCursor += sizeof(uint32_t);
         if (!iType)
         if (!iType)
             throw DeadlyImportError("Unable to read HMP7 skin chunk");
             throw DeadlyImportError("Unable to read HMP7 skin chunk");
 
 

+ 5 - 9
code/IFCLoader.cpp

@@ -707,15 +707,11 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
         }
         }
 
 
         if (!properties.empty()) {
         if (!properties.empty()) {
-            aiMetadata* data = new aiMetadata();
-            data->mNumProperties = static_cast<unsigned int>(properties.size());
-            data->mKeys = new aiString[data->mNumProperties]();
-            data->mValues = new aiMetadataEntry[data->mNumProperties]();
-
-            unsigned int index = 0;
-            for(const Metadata::value_type& kv : properties)
-                data->Set(index++, kv.first, aiString(kv.second));
-
+            aiMetadata* data = aiMetadata::Alloc( static_cast<unsigned int>(properties.size()) );
+            unsigned int index( 0 );
+            for ( const Metadata::value_type& kv : properties ) {
+                data->Set( index++, kv.first, aiString( kv.second ) );
+            }
             nd->mMetaData = data;
             nd->mMetaData = data;
         }
         }
     }
     }

+ 3 - 2
code/IRRLoader.cpp

@@ -269,14 +269,15 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
         if (UINT_MAX == defMatIdx)
         if (UINT_MAX == defMatIdx)
         {
         {
             defMatIdx = (unsigned int)materials.size();
             defMatIdx = (unsigned int)materials.size();
-            aiMaterial* mat = new aiMaterial();
+            //TODO: add this materials to someone?
+            /*aiMaterial* mat = new aiMaterial();
 
 
             aiString s;
             aiString s;
             s.Set(AI_DEFAULT_MATERIAL_NAME);
             s.Set(AI_DEFAULT_MATERIAL_NAME);
             mat->AddProperty(&s,AI_MATKEY_NAME);
             mat->AddProperty(&s,AI_MATKEY_NAME);
 
 
             aiColor3D c(0.6f,0.6f,0.6f);
             aiColor3D c(0.6f,0.6f,0.6f);
-            mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
+            mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);*/
         }
         }
         mesh->mMaterialIndex = defMatIdx;
         mesh->mMaterialIndex = defMatIdx;
         return;
         return;

+ 25 - 21
code/IRRMeshLoader.cpp

@@ -116,14 +116,18 @@ const aiImporterDesc* IRRMeshImporter::GetInfo () const
     return &desc;
     return &desc;
 }
 }
 
 
-static void releaseMaterial( aiMaterial *mat ) {
-    delete mat;
-    mat = nullptr;
+static void releaseMaterial( aiMaterial **mat ) {
+    if(*mat!= nullptr) {
+        delete *mat;
+        *mat = nullptr;
+    }
 }
 }
 
 
-static void releaseMesh( aiMesh *mesh ) {
-    delete mesh;
-    mesh = nullptr;
+static void releaseMesh( aiMesh **mesh ) {
+    if (*mesh != nullptr){
+        delete *mesh;
+        *mesh = nullptr;
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -148,8 +152,8 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
     meshes.reserve(5);
     meshes.reserve(5);
 
 
     // temporary data - current mesh buffer
     // temporary data - current mesh buffer
-    aiMaterial* curMat  = NULL;
-    aiMesh* curMesh     = NULL;
+    aiMaterial* curMat  = nullptr;
+    aiMesh* curMesh     = nullptr;
     unsigned int curMatFlags = 0;
     unsigned int curMatFlags = 0;
 
 
     std::vector<aiVector3D> curVertices,curNormals,curTangents,curBitangents;
     std::vector<aiVector3D> curVertices,curNormals,curTangents,curBitangents;
@@ -170,14 +174,14 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                 // end of previous buffer. A material and a mesh should be there
                 // end of previous buffer. A material and a mesh should be there
                 if ( !curMat || !curMesh)   {
                 if ( !curMat || !curMesh)   {
                     DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");                    
                     DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");                    
-                    releaseMaterial( curMat );
-                    releaseMesh( curMesh );
+                    releaseMaterial( &curMat );
+                    releaseMesh( &curMesh );
                 } else {
                 } else {
                     materials.push_back(curMat);
                     materials.push_back(curMat);
                     meshes.push_back(curMesh);
                     meshes.push_back(curMesh);
                 }
                 }
-                curMat  = NULL;
-                curMesh = NULL;
+                curMat  = nullptr;
+                curMesh = nullptr;
 
 
                 curVertices.clear();
                 curVertices.clear();
                 curColors.clear();
                 curColors.clear();
@@ -192,7 +196,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
             if (!ASSIMP_stricmp(reader->getNodeName(),"material"))  {
             if (!ASSIMP_stricmp(reader->getNodeName(),"material"))  {
                 if (curMat) {
                 if (curMat) {
                     DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
                     DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
-                    releaseMaterial( curMat );
+                    releaseMaterial( &curMat );
                 }
                 }
                 curMat = ParseMaterial(curMatFlags);
                 curMat = ParseMaterial(curMatFlags);
             }
             }
@@ -204,8 +208,8 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                     // This is possible ... remove the mesh from the list and skip further reading
                     // This is possible ... remove the mesh from the list and skip further reading
                     DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
                     DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
 
 
-                    releaseMaterial( curMat );
-                    releaseMesh( curMesh );
+                    releaseMaterial( &curMat );
+                    releaseMesh( &curMesh );
                     textMeaning = 0;
                     textMeaning = 0;
                     continue;
                     continue;
                 }
                 }
@@ -248,7 +252,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                     vertexFormat = 2;
                     vertexFormat = 2;
                 }
                 }
                 else if (ASSIMP_stricmp("standard", t)) {
                 else if (ASSIMP_stricmp("standard", t)) {
-                    releaseMaterial( curMat );
+                    releaseMaterial( &curMat );
                     DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
                     DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
                 }
                 }
                 else vertexFormat = 0;
                 else vertexFormat = 0;
@@ -256,7 +260,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
             }
             }
             else if (!ASSIMP_stricmp(reader->getNodeName(),"indices"))  {
             else if (!ASSIMP_stricmp(reader->getNodeName(),"indices"))  {
                 if (curVertices.empty() && curMat)  {
                 if (curVertices.empty() && curMat)  {
-                    releaseMaterial( curMat );
+                    releaseMaterial( &curMat );
                     throw DeadlyImportError("IRRMESH: indices must come after vertices");
                     throw DeadlyImportError("IRRMESH: indices must come after vertices");
                 }
                 }
 
 
@@ -272,10 +276,10 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                     DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
                     DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
 
 
                     // mesh - away
                     // mesh - away
-                    releaseMesh( curMesh );
+                    releaseMesh( &curMesh );
 
 
                     // material - away
                     // material - away
-                    releaseMaterial( curMat );
+                    releaseMaterial( &curMat );
 
 
                     textMeaning = 0;
                     textMeaning = 0;
                     continue;
                     continue;
@@ -487,8 +491,8 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
     if (curMat || curMesh)  {
     if (curMat || curMesh)  {
         if ( !curMat || !curMesh)   {
         if ( !curMat || !curMesh)   {
             DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
             DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
-            releaseMaterial( curMat );
-            releaseMesh( curMesh );
+            releaseMaterial( &curMat );
+            releaseMesh( &curMesh );
         }
         }
         else    {
         else    {
             materials.push_back(curMat);
             materials.push_back(curMat);

+ 3 - 3
code/LWOLoader.cpp

@@ -1058,8 +1058,6 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
     LWO::PointList& pointList = mCurLayer->mTempPoints;
     LWO::PointList& pointList = mCurLayer->mTempPoints;
     LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
     LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
 
 
-    float temp[4];
-
     const unsigned int numPoints = (unsigned int)pointList.size();
     const unsigned int numPoints = (unsigned int)pointList.size();
     const unsigned int numFaces  = (unsigned int)list.size();
     const unsigned int numFaces  = (unsigned int)list.size();
 
 
@@ -1123,10 +1121,12 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
                 }
                 }
             }
             }
         }
         }
+
+        std::unique_ptr<float[]> temp(new float[type]);
         for (unsigned int l = 0; l < type;++l)
         for (unsigned int l = 0; l < type;++l)
             temp[l] = GetF4();
             temp[l] = GetF4();
 
 
-        DoRecursiveVMAPAssignment(base,type,idx, temp);
+        DoRecursiveVMAPAssignment(base,type,idx, temp.get());
         mFileBuffer += diff;
         mFileBuffer += diff;
     }
     }
 }
 }

+ 4 - 4
code/MDLLoader.cpp

@@ -172,8 +172,7 @@ void MDLImporter::InternReadFile( const std::string& pFile,
     }
     }
 
 
     // Allocate storage and copy the contents of the file to a memory buffer
     // Allocate storage and copy the contents of the file to a memory buffer
-    std::vector<unsigned char> buffer(iFileSize+1);
-    mBuffer = &buffer[0];
+    mBuffer =new unsigned char[iFileSize+1];
     file->Read( (void*)mBuffer, 1, iFileSize);
     file->Read( (void*)mBuffer, 1, iFileSize);
 
 
     // Append a binary zero to the end of the buffer.
     // Append a binary zero to the end of the buffer.
@@ -239,7 +238,8 @@ void MDLImporter::InternReadFile( const std::string& pFile,
         0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
         0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
 
 
     // delete the file buffer and cleanup
     // delete the file buffer and cleanup
-    AI_DEBUG_INVALIDATE_PTR(mBuffer);
+    delete [] mBuffer;
+    mBuffer= nullptr;
     AI_DEBUG_INVALIDATE_PTR(pIOHandler);
     AI_DEBUG_INVALIDATE_PTR(pIOHandler);
     AI_DEBUG_INVALIDATE_PTR(pScene);
     AI_DEBUG_INVALIDATE_PTR(pScene);
 }
 }
@@ -1557,7 +1557,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 			} else {
 			} else {
 				pcNode->mName.length = ::strlen(szBuffer);
 				pcNode->mName.length = ::strlen(szBuffer);
 			}
 			}
-            ::strcpy(pcNode->mName.data,szBuffer);
+            ::strncpy(pcNode->mName.data,szBuffer,MAXLEN-1);
             ++p;
             ++p;
         }
         }
     }
     }

+ 5 - 2
code/MDLMaterialLoader.cpp

@@ -488,7 +488,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
     unsigned int iWidth,
     unsigned int iWidth,
     unsigned int iHeight)
     unsigned int iHeight)
 {
 {
-    aiTexture* pcNew = NULL;
+    aiTexture* pcNew = nullptr;
 
 
     // get the type of the skin
     // get the type of the skin
     unsigned int iMasked = (unsigned int)(iType & 0xF);
     unsigned int iMasked = (unsigned int)(iType & 0xF);
@@ -522,7 +522,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
         memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
         memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
         szCurrent += iWidth;
         szCurrent += iWidth;
     }
     }
-    if (0x7 == iMasked)
+    else if (0x7 == iMasked)
     {
     {
         // ***** REFERENCE TO EXTERNAL FILE *****
         // ***** REFERENCE TO EXTERNAL FILE *****
         if (1 != iHeight)
         if (1 != iHeight)
@@ -546,6 +546,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
     else if (iMasked || !iType || (iType && iWidth && iHeight))
     else if (iMasked || !iType || (iType && iWidth && iHeight))
     {
     {
         // ***** STANDARD COLOR TEXTURE *****
         // ***** STANDARD COLOR TEXTURE *****
+        if(pcNew!= nullptr)
+            delete pcNew;
+
         pcNew = new aiTexture();
         pcNew = new aiTexture();
         if (!iHeight || !iWidth)
         if (!iHeight || !iWidth)
         {
         {

+ 3 - 1
code/MakeVerboseFormat.cpp

@@ -168,6 +168,8 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
         }
         }
     }
     }
 
 
+
+
     // build output vertex weights
     // build output vertex weights
     for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
     for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
     {
     {
@@ -177,11 +179,11 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
             aiVertexWeight *weightToCopy = &( newWeights[i][0] );
             aiVertexWeight *weightToCopy = &( newWeights[i][0] );
             memcpy(pcMesh->mBones[i]->mWeights, weightToCopy,
             memcpy(pcMesh->mBones[i]->mWeights, weightToCopy,
                 sizeof(aiVertexWeight) * newWeights[i].size());
                 sizeof(aiVertexWeight) * newWeights[i].size());
-            delete[] newWeights;
         } else {
         } else {
             pcMesh->mBones[i]->mWeights = NULL;
             pcMesh->mBones[i]->mWeights = NULL;
         }
         }
     }
     }
+    delete[] newWeights;
 
 
     // delete the old members
     // delete the old members
     delete[] pcMesh->mVertices;
     delete[] pcMesh->mVertices;

+ 4 - 2
code/NDOLoader.cpp

@@ -257,7 +257,8 @@ void NDOImporter::InternReadFile( const std::string& pFile,
         }
         }
 
 
         aiMesh* mesh = new aiMesh();
         aiMesh* mesh = new aiMesh();
-        aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces=static_cast<unsigned int>(face_table.size())];
+        mesh->mNumFaces=static_cast<unsigned int>(face_table.size());
+        aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
 
 
         vertices.clear();
         vertices.clear();
         vertices.reserve(4 * face_table.size()); // arbitrarily chosen
         vertices.reserve(4 * face_table.size()); // arbitrarily chosen
@@ -298,7 +299,8 @@ void NDOImporter::InternReadFile( const std::string& pFile,
             pScene->mMeshes[pScene->mNumMeshes] = mesh;
             pScene->mMeshes[pScene->mNumMeshes] = mesh;
 
 
             (nd->mMeshes = new unsigned int[nd->mNumMeshes=1])[0]=pScene->mNumMeshes++;
             (nd->mMeshes = new unsigned int[nd->mNumMeshes=1])[0]=pScene->mNumMeshes++;
-        }
+        }else
+            delete mesh;
     }
     }
 }
 }
 
 

+ 1 - 0
code/ObjFileParser.cpp

@@ -451,6 +451,7 @@ void ObjFileParser::getFace( aiPrimitiveType type ) {
         DefaultLogger::get()->error("Obj: Ignoring empty face");
         DefaultLogger::get()->error("Obj: Ignoring empty face");
         // skip line and clean up
         // skip line and clean up
         m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
         m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+        delete face;
         return;
         return;
     }
     }
 
 

+ 2 - 5
code/SIBImporter.cpp

@@ -901,11 +901,8 @@ void SIBImporter::InternReadFile(const std::string& pFile,
         // Mark instanced objects as being so.
         // Mark instanced objects as being so.
         if (n >= firstInst)
         if (n >= firstInst)
         {
         {
-            node->mMetaData = new aiMetadata;
-            node->mMetaData->mNumProperties = 1;
-            node->mMetaData->mKeys = new aiString[1];
-            node->mMetaData->mValues = new aiMetadataEntry[1];
-            node->mMetaData->Set(0, "IsInstance", true);
+            node->mMetaData = aiMetadata::Alloc( 1 );
+            node->mMetaData->Set( 0, "IsInstance", true );
         }
         }
     }
     }
 
 

+ 2 - 2
code/SMDLoader.cpp

@@ -641,7 +641,7 @@ void SMDImporter::ComputeAbsoluteBoneTransformations()
         bone.mOffsetMatrix.Inverse();
         bone.mOffsetMatrix.Inverse();
     }
     }
 }
 }
-
+\
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // create output materials
 // create output materials
 void SMDImporter::CreateOutputMaterials()
 void SMDImporter::CreateOutputMaterials()
@@ -660,7 +660,7 @@ void SMDImporter::CreateOutputMaterials()
 
 
         if (aszTextures[iMat].length())
         if (aszTextures[iMat].length())
         {
         {
-            ::strcpy(szName.data, aszTextures[iMat].c_str() );
+            ::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1);
             szName.length = aszTextures[iMat].length();
             szName.length = aszTextures[iMat].length();
             pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
             pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
         }
         }

+ 1 - 1
code/STLLoader.cpp

@@ -274,7 +274,7 @@ void STLImporter::LoadASCIIFile()
         }
         }
         else pScene->mRootNode->mName.Set("<STL_ASCII>");
         else pScene->mRootNode->mName.Set("<STL_ASCII>");
 
 
-        unsigned int faceVertexCounter = 0;
+        unsigned int faceVertexCounter = 3;
         for ( ;; )
         for ( ;; )
         {
         {
             // go to the next token
             // go to the next token

+ 14 - 13
code/SceneCombiner.cpp

@@ -43,11 +43,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // possible as new fields are added to assimp structures.
 // possible as new fields are added to assimp structures.
 
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
-/** @file Implements Assimp::SceneCombiner. This is a smart utility
- *    class that combines multiple scenes, meshes, ... into one. Currently
- *    these utilities are used by the IRR and LWS loaders and the
- *    OptimizeGraph step.
- */
+/** 
+  * @file Implements Assimp::SceneCombiner. This is a smart utility
+  *       class that combines multiple scenes, meshes, ... into one. Currently
+  *       these utilities are used by the IRR and LWS loaders and the
+  *       OptimizeGraph step.
+  */
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 #include "SceneCombiner.h"
 #include "SceneCombiner.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
@@ -59,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <stdio.h>
 #include <stdio.h>
 #include "ScenePrivate.h"
 #include "ScenePrivate.h"
 
 
-namespace Assimp    {
+namespace Assimp {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Add a prefix to a string
 // Add a prefix to a string
@@ -198,8 +199,9 @@ void SceneCombiner::MergeScenes(aiScene** _dest,std::vector<aiScene*>& src,
 void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInfo>& srcList)
 void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInfo>& srcList)
 {
 {
     unsigned int cnt;
     unsigned int cnt;
-    for (cnt = 0; cnt < attach->mNumChildren;++cnt)
-        AttachToGraph(attach->mChildren[cnt],srcList);
+    for ( cnt = 0; cnt < attach->mNumChildren; ++cnt ) {
+        AttachToGraph( attach->mChildren[ cnt ], srcList );
+    }
 
 
     cnt = 0;
     cnt = 0;
     for (std::vector<NodeAttachmentInfo>::iterator it = srcList.begin();
     for (std::vector<NodeAttachmentInfo>::iterator it = srcList.begin();
@@ -1219,13 +1221,12 @@ void SceneCombiner::Copy     (aiNode** _dest, const aiNode* src)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiMetadata** _dest, const aiMetadata* src)
+void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src)
 {
 {
-    ai_assert(NULL != _dest && NULL != src);
+    ai_assert( NULL != _dest );
+    ai_assert( NULL != src);
 
 
-    aiMetadata* dest = *_dest = new aiMetadata();
-    dest->mNumProperties = src->mNumProperties;
-    dest->mKeys = new aiString[src->mNumProperties];
+    aiMetadata* dest = *_dest = aiMetadata::Alloc( src->mNumProperties );
     std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys);
     std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys);
 
 
     dest->mValues = new aiMetadataEntry[src->mNumProperties];
     dest->mValues = new aiMetadataEntry[src->mNumProperties];

+ 6 - 9
code/Subdivision.cpp

@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "SpatialSort.h"
 #include "SpatialSort.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
 #include "Vertex.h"
 #include "Vertex.h"
+#include <assimp/ai_assert.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
 using namespace Assimp;
 using namespace Assimp;
@@ -55,9 +56,7 @@ void mydummy() {}
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 class CatmullClarkSubdivider : public Subdivider
 class CatmullClarkSubdivider : public Subdivider
 {
 {
-
 public:
 public:
-
     void Subdivide (aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input);
     void Subdivide (aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input);
     void Subdivide (aiMesh** smesh, size_t nmesh,
     void Subdivide (aiMesh** smesh, size_t nmesh,
         aiMesh** out, unsigned int num, bool discard_input);
         aiMesh** out, unsigned int num, bool discard_input);
@@ -74,8 +73,6 @@ public:
         unsigned int ref;
         unsigned int ref;
     };
     };
 
 
-
-
     typedef std::vector<unsigned int> UIntVector;
     typedef std::vector<unsigned int> UIntVector;
     typedef std::map<uint64_t,Edge> EdgeMap;
     typedef std::map<uint64_t,Edge> EdgeMap;
 
 
@@ -99,7 +96,6 @@ public:
     unsigned int eh_tmp0__, eh_tmp1__;
     unsigned int eh_tmp0__, eh_tmp1__;
 
 
 private:
 private:
-
     void InternSubdivide (const aiMesh* const * smesh,
     void InternSubdivide (const aiMesh* const * smesh,
         size_t nmesh,aiMesh** out, unsigned int num);
         size_t nmesh,aiMesh** out, unsigned int num);
 };
 };
@@ -128,7 +124,8 @@ void  CatmullClarkSubdivider::Subdivide (
     bool discard_input
     bool discard_input
     )
     )
 {
 {
-    assert(mesh != out);
+    ai_assert(mesh != out);
+    
     Subdivide(&mesh,1,&out,num,discard_input);
     Subdivide(&mesh,1,&out,num,discard_input);
 }
 }
 
 
@@ -142,12 +139,12 @@ void CatmullClarkSubdivider::Subdivide (
     bool discard_input
     bool discard_input
     )
     )
 {
 {
-    ai_assert(NULL != smesh && NULL != out);
+    ai_assert( NULL != smesh );
+    ai_assert( NULL != out );
 
 
     // course, both regions may not overlap
     // course, both regions may not overlap
-    assert(smesh<out || smesh+nmesh>out+nmesh);
+    ai_assert(smesh<out || smesh+nmesh>out+nmesh);
     if (!num) {
     if (!num) {
-
         // No subdivision at all. Need to copy all the meshes .. argh.
         // No subdivision at all. Need to copy all the meshes .. argh.
         if (discard_input) {
         if (discard_input) {
             for (size_t s = 0; s < nmesh; ++s) {
             for (size_t s = 0; s < nmesh; ++s) {

+ 8 - 2
code/X3DImporter.cpp

@@ -1480,10 +1480,11 @@ void X3DImporter::ParseNode_Head()
 				XML_CheckNode_MustBeEmpty();
 				XML_CheckNode_MustBeEmpty();
 
 
 				// adding metadata from <head> as MetaString from <Scene>
 				// adding metadata from <head> as MetaString from <Scene>
-				CX3DImporter_NodeElement_MetaString* ms = new CX3DImporter_NodeElement_MetaString(NodeElement_Cur);
+                bool added( false );
+                CX3DImporter_NodeElement_MetaString* ms = new CX3DImporter_NodeElement_MetaString(NodeElement_Cur);
 
 
 				ms->Name = mReader->getAttributeValueSafe("name");
 				ms->Name = mReader->getAttributeValueSafe("name");
-				// name can not be empty
+				// name must not be empty
 				if(!ms->Name.empty())
 				if(!ms->Name.empty())
 				{
 				{
 					ms->Value.push_back(mReader->getAttributeValueSafe("content"));
 					ms->Value.push_back(mReader->getAttributeValueSafe("content"));
@@ -1491,8 +1492,13 @@ void X3DImporter::ParseNode_Head()
                     if ( NodeElement_Cur != nullptr )
                     if ( NodeElement_Cur != nullptr )
                     {
                     {
                         NodeElement_Cur->Child.push_back( ms );
                         NodeElement_Cur->Child.push_back( ms );
+                        added = true;
                     }
                     }
 				}
 				}
+                // if an error has occurred, release instance
+                if ( !added ) {
+                    delete ms;
+                }
 			}// if(XML_CheckNode_NameEqual("meta"))
 			}// if(XML_CheckNode_NameEqual("meta"))
 		}// if(mReader->getNodeType() == irr::io::EXN_ELEMENT)
 		}// if(mReader->getNodeType() == irr::io::EXN_ELEMENT)
 		else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
 		else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END)

+ 6 - 8
code/X3DImporter_Node.hpp

@@ -130,37 +130,35 @@ public:
 public:
 public:
 
 
 	std::string ID;///< ID of the element. Can be empty. In X3D synonym for "ID" attribute.
 	std::string ID;///< ID of the element. Can be empty. In X3D synonym for "ID" attribute.
-	CX3DImporter_NodeElement* Parent;///< Parrent element. If nullptr then this node is root.
+	CX3DImporter_NodeElement* Parent;///< Parent element. If nullptr then this node is root.
 	std::list<CX3DImporter_NodeElement*> Child;///< Child elements.
 	std::list<CX3DImporter_NodeElement*> Child;///< Child elements.
 
 
 	/***********************************************/
 	/***********************************************/
 	/****************** Functions ******************/
 	/****************** Functions ******************/
 	/***********************************************/
 	/***********************************************/
 
 
-private:
+    /// @brief  The destructor, virtual.
+    virtual ~CX3DImporter_NodeElement() {
+        // empty
+    }
 
 
-	/// \fn CX3DImporter_NodeElement(const CX3DImporter_NodeElement& pNodeElement)
+private:
 	/// Disabled copy constructor.
 	/// Disabled copy constructor.
 	CX3DImporter_NodeElement(const CX3DImporter_NodeElement& pNodeElement);
 	CX3DImporter_NodeElement(const CX3DImporter_NodeElement& pNodeElement);
 
 
-	/// \fn CX3DImporter_NodeElement& operator=(const CX3DImporter_NodeElement& pNodeElement)
 	/// Disabled assign operator.
 	/// Disabled assign operator.
 	CX3DImporter_NodeElement& operator=(const CX3DImporter_NodeElement& pNodeElement);
 	CX3DImporter_NodeElement& operator=(const CX3DImporter_NodeElement& pNodeElement);
 
 
-	/// \fn CX3DImporter_NodeElement()
 	/// Disabled default constructor.
 	/// Disabled default constructor.
 	CX3DImporter_NodeElement();
 	CX3DImporter_NodeElement();
 
 
 protected:
 protected:
-
-	/// \fn CX3DImporter_NodeElement(const EType pType, CX3DImporter_NodeElement* pParent)
 	/// In constructor inheritor must set element type.
 	/// In constructor inheritor must set element type.
 	/// \param [in] pType - element type.
 	/// \param [in] pType - element type.
 	/// \param [in] pParent - parent element.
 	/// \param [in] pParent - parent element.
 	CX3DImporter_NodeElement(const EType pType, CX3DImporter_NodeElement* pParent)
 	CX3DImporter_NodeElement(const EType pType, CX3DImporter_NodeElement* pParent)
 		: Type(pType), Parent(pParent)
 		: Type(pType), Parent(pParent)
 	{}
 	{}
-
 };// class IX3DImporter_NodeElement
 };// class IX3DImporter_NodeElement
 
 
 /// \class CX3DImporter_NodeElement_Group
 /// \class CX3DImporter_NodeElement_Group

+ 7 - 8
code/X3DImporter_Postprocess.cpp

@@ -758,15 +758,14 @@ void X3DImporter::Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pN
     size_t meta_idx;
     size_t meta_idx;
 
 
 	PostprocessHelper_CollectMetadata(pNodeElement, meta_list);// find metadata in current node element.
 	PostprocessHelper_CollectMetadata(pNodeElement, meta_list);// find metadata in current node element.
-	if(meta_list.size() > 0)
+	if ( !meta_list.empty() )
 	{
 	{
-		if(pSceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
+        if ( pSceneNode.mMetaData != nullptr ) {
+            throw DeadlyImportError( "Postprocess. MetaData member in node are not nullptr. Something went wrong." );
+        }
 
 
-		// copy collected metadata to output node.
-		pSceneNode.mMetaData = new aiMetadata();
-		pSceneNode.mMetaData->mNumProperties = meta_list.size();
-		pSceneNode.mMetaData->mKeys = new aiString[pSceneNode.mMetaData->mNumProperties];
-		pSceneNode.mMetaData->mValues = new aiMetadataEntry[pSceneNode.mMetaData->mNumProperties];
+		// copy collected metadata to output node.        
+        pSceneNode.mMetaData = aiMetadata::Alloc( meta_list.size() );
 		meta_idx = 0;
 		meta_idx = 0;
 		for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++, meta_idx++)
 		for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++, meta_idx++)
 		{
 		{
@@ -808,7 +807,7 @@ void X3DImporter::Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pN
 				throw DeadlyImportError("Postprocess. Unknown metadata type.");
 				throw DeadlyImportError("Postprocess. Unknown metadata type.");
 			}// if((*it)->Type == CX3DImporter_NodeElement::ENET_Meta*) else
 			}// if((*it)->Type == CX3DImporter_NodeElement::ENET_Meta*) else
 		}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
 		}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
-	}// if(meta_list.size() > 0)
+	}// if( !meta_list.empty() )
 }
 }
 
 
 }// namespace Assimp
 }// namespace Assimp

+ 1 - 1
code/XFileExporter.cpp

@@ -513,7 +513,7 @@ std::string XFileExporter::toXFileString(aiString &name)
     return str;
     return str;
 }
 }
 
 
-void XFileExporter::writePath(aiString path)
+void XFileExporter::writePath(const aiString &path)
 {
 {
     std::string str = std::string(path.C_Str());
     std::string str = std::string(path.C_Str());
     BaseImporter::ConvertUTF8toISO8859_1(str);
     BaseImporter::ConvertUTF8toISO8859_1(str);

+ 1 - 1
code/XFileExporter.h

@@ -107,7 +107,7 @@ protected:
     const ExportProperties* mProperties;
     const ExportProperties* mProperties;
 
 
     /// write a path
     /// write a path
-    void writePath(aiString path);
+    void writePath(const aiString &path);
 
 
     /// The IOSystem for output
     /// The IOSystem for output
     IOSystem* mIOSystem;
     IOSystem* mIOSystem;

+ 11 - 2
code/glTFAsset.h

@@ -744,6 +744,10 @@ namespace glTF
 			SExtension(const EType pType)
 			SExtension(const EType pType)
 				: Type(pType)
 				: Type(pType)
 			{}
 			{}
+
+            virtual ~SExtension() {
+                // empty
+            }
 		};
 		};
 
 
 		#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
 		#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
@@ -765,8 +769,13 @@ namespace glTF
 				/// \fn SCompression_Open3DGC
 				/// \fn SCompression_Open3DGC
 				/// Constructor.
 				/// Constructor.
 				SCompression_Open3DGC()
 				SCompression_Open3DGC()
-				: SExtension(Compression_Open3DGC)
-				{}
+				: SExtension(Compression_Open3DGC) {
+                    // empty
+                }
+
+                virtual ~SCompression_Open3DGC() {
+                    // empty
+                }
 			};
 			};
 		#endif
 		#endif
 
 

+ 17 - 5
code/glTFAsset.inl

@@ -1005,6 +1005,12 @@ Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer);
 		size_t tval = ifs.GetNIntAttribute(static_cast<unsigned long>(idx));
 		size_t tval = ifs.GetNIntAttribute(static_cast<unsigned long>(idx));
 		switch( ifs.GetIntAttributeType(static_cast<unsigned long>(idx) ) )
 		switch( ifs.GetIntAttributeType(static_cast<unsigned long>(idx) ) )
 		{
 		{
+            case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN:
+            case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX:
+            case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID:
+            case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID:
+                break;
+
 			default:
 			default:
 				throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
 				throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
 		}
 		}
@@ -1049,10 +1055,14 @@ Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer);
 		}
 		}
 	}
 	}
 
 
-	for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++)
-	{
-		switch(ifs.GetIntAttributeType(static_cast<unsigned long>(idx)))
-		{
+	for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) {
+		switch(ifs.GetIntAttributeType(static_cast<unsigned int>(idx))) {
+            case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN:
+            case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX:
+            case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID:
+            case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID:
+                break;
+
 			// ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint)));
 			// ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint)));
 			default:
 			default:
 				throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
 				throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
@@ -1062,7 +1072,9 @@ Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer);
 	//
 	//
 	// Decode data
 	// Decode data
 	//
 	//
-	if(decoder.DecodePayload(ifs, bstream) != o3dgc::O3DGC_OK) throw DeadlyImportError("GLTF: can not decode Open3DGC data.");
+    if ( decoder.DecodePayload( ifs, bstream ) != o3dgc::O3DGC_OK ) {
+        throw DeadlyImportError( "GLTF: can not decode Open3DGC data." );
+    }
 
 
 	// Set encoded region for "buffer".
 	// Set encoded region for "buffer".
 	buf->EncodedRegion_Mark(pCompression_Open3DGC.Offset, pCompression_Open3DGC.Count, decoded_data, decoded_data_size, id);
 	buf->EncodedRegion_Mark(pCompression_Open3DGC.Offset, pCompression_Open3DGC.Count, decoded_data, decoded_data_size, id);

+ 35 - 21
code/glTFExporter.cpp

@@ -37,9 +37,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 */
 */
-
-
-
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
 #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
 
 
@@ -94,8 +91,6 @@ namespace Assimp {
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 
-
-
 glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
 glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
                            const ExportProperties* pProperties, bool isBinary)
                            const ExportProperties* pProperties, bool isBinary)
     : mFilename(filename)
     : mFilename(filename)
@@ -418,17 +413,18 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin>& skinRef)
     return parentNodeRef;
     return parentNodeRef;
 }
 }
 
 
-void ExportSkin(Asset& mAsset, const aiMesh* aim, Ref<Mesh>& meshRef, Ref<Buffer>& bufferRef, Ref<Skin>& skinRef, std::vector<aiMatrix4x4>& inverseBindMatricesData)
+void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buffer>& bufferRef, Ref<Skin>& skinRef, std::vector<aiMatrix4x4>& inverseBindMatricesData)
 {
 {
-    if (aim->mNumBones < 1) {
+    if (aimesh->mNumBones < 1) {
         return;
         return;
     }
     }
 
 
     // Store the vertex joint and weight data.
     // Store the vertex joint and weight data.
-    vec4* vertexJointData = new vec4[aim->mNumVertices];
-    vec4* vertexWeightData = new vec4[aim->mNumVertices];
-    int* jointsPerVertex = new int[aim->mNumVertices];
-    for (size_t i = 0; i < aim->mNumVertices; ++i) {
+    const size_t NumVerts( aimesh->mNumVertices );
+    vec4* vertexJointData = new vec4[ NumVerts ];
+    vec4* vertexWeightData = new vec4[ NumVerts ];
+    int* jointsPerVertex = new int[ NumVerts ];
+    for (size_t i = 0; i < NumVerts; ++i) {
         jointsPerVertex[i] = 0;
         jointsPerVertex[i] = 0;
         for (size_t j = 0; j < 4; ++j) {
         for (size_t j = 0; j < 4; ++j) {
             vertexJointData[i][j] = 0;
             vertexJointData[i][j] = 0;
@@ -436,8 +432,8 @@ void ExportSkin(Asset& mAsset, const aiMesh* aim, Ref<Mesh>& meshRef, Ref<Buffer
         }
         }
     }
     }
 
 
-    for (unsigned int idx_bone = 0; idx_bone < aim->mNumBones; ++idx_bone) {
-        const aiBone* aib = aim->mBones[idx_bone];
+    for (unsigned int idx_bone = 0; idx_bone < aimesh->mNumBones; ++idx_bone) {
+        const aiBone* aib = aimesh->mBones[idx_bone];
 
 
         // aib->mName   =====>  skinRef->jointNames
         // aib->mName   =====>  skinRef->jointNames
         // Find the node with id = mName.
         // Find the node with id = mName.
@@ -469,7 +465,9 @@ void ExportSkin(Asset& mAsset, const aiMesh* aim, Ref<Mesh>& meshRef, Ref<Buffer
             float vertWeight      = aib->mWeights[idx_weights].mWeight;
             float vertWeight      = aib->mWeights[idx_weights].mWeight;
 
 
             // A vertex can only have at most four joint weights. Ignore all others.
             // A vertex can only have at most four joint weights. Ignore all others.
-            if (jointsPerVertex[vertexId] > 3) { continue; }
+            if (jointsPerVertex[vertexId] > 3) { 
+                continue; 
+            }
 
 
             vertexJointData[vertexId][jointsPerVertex[vertexId]] = jointNamesIndex;
             vertexJointData[vertexId][jointsPerVertex[vertexId]] = jointNamesIndex;
             vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
             vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
@@ -480,11 +478,18 @@ void ExportSkin(Asset& mAsset, const aiMesh* aim, Ref<Mesh>& meshRef, Ref<Buffer
     } // End: for-loop mNumMeshes
     } // End: for-loop mNumMeshes
 
 
     Mesh::Primitive& p = meshRef->primitives.back();
     Mesh::Primitive& p = meshRef->primitives.back();
-    Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aim->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
-    if (vertexJointAccessor) p.attributes.joint.push_back(vertexJointAccessor);
+    Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+    if ( vertexJointAccessor ) {
+        p.attributes.joint.push_back( vertexJointAccessor );
+    }
 
 
-    Ref<Accessor> vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aim->mNumVertices, vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
-    if (vertexWeightAccessor) p.attributes.weight.push_back(vertexWeightAccessor);
+    Ref<Accessor> vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+    if ( vertexWeightAccessor ) {
+        p.attributes.weight.push_back( vertexWeightAccessor );
+    }
+    delete[] jointsPerVertex;
+    delete[] vertexWeightData;
+    delete[] vertexJointData;
 }
 }
 
 
 void glTFExporter::ExportMeshes()
 void glTFExporter::ExportMeshes()
@@ -864,7 +869,10 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
         }
         }
 
 
         Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumPositionKeys, translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
         Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumPositionKeys, translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
-        if (tranAccessor) animRef->Parameters.translation = tranAccessor;
+        if ( tranAccessor ) {
+            animRef->Parameters.translation = tranAccessor;
+        }
+        delete[] translationData;
     }
     }
 
 
     //-------------------------------------------------------
     //-------------------------------------------------------
@@ -876,7 +884,10 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
         }
         }
 
 
         Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumScalingKeys, scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
         Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumScalingKeys, scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
-        if (scaleAccessor) animRef->Parameters.scale = scaleAccessor;
+        if ( scaleAccessor ) {
+            animRef->Parameters.scale = scaleAccessor;
+        }
+        delete[] scaleData;
     }
     }
 
 
     //-------------------------------------------------------
     //-------------------------------------------------------
@@ -891,7 +902,10 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
         }
         }
 
 
         Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumRotationKeys, rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
         Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumRotationKeys, rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
-        if (rotAccessor) animRef->Parameters.rotation = rotAccessor;
+        if ( rotAccessor ) {
+            animRef->Parameters.rotation = rotAccessor;
+        }
+        delete[] rotationData;
     }
     }
 }
 }
 
 

+ 75 - 55
include/assimp/metadata.h

@@ -46,24 +46,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_METADATA_H_INC
 #ifndef AI_METADATA_H_INC
 #define AI_METADATA_H_INC
 #define AI_METADATA_H_INC
 
 
-#include <assert.h>
-
 #if defined(_MSC_VER) && (_MSC_VER <= 1500)
 #if defined(_MSC_VER) && (_MSC_VER <= 1500)
-#include "Compiler/pstdint.h"
+#  include "Compiler/pstdint.h"
 #else
 #else
-#include <limits.h>
-#include <stdint.h>
+#  include <stdint.h>
 #endif
 #endif
 
 
-
-
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /**
 /**
   * Enum used to distinguish data types
   * Enum used to distinguish data types
   */
   */
  // -------------------------------------------------------------------------------
  // -------------------------------------------------------------------------------
-typedef enum aiMetadataType
-{
+typedef enum aiMetadataType {
     AI_BOOL       = 0,
     AI_BOOL       = 0,
     AI_INT32      = 1,
     AI_INT32      = 1,
     AI_UINT64     = 2,
     AI_UINT64     = 2,
@@ -77,8 +71,6 @@ typedef enum aiMetadataType
 #endif
 #endif
 } aiMetadataType;
 } aiMetadataType;
 
 
-
-
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /**
 /**
   * Metadata entry
   * Metadata entry
@@ -86,8 +78,7 @@ typedef enum aiMetadataType
   * The type field uniquely identifies the underlying type of the data field
   * The type field uniquely identifies the underlying type of the data field
   */
   */
  // -------------------------------------------------------------------------------
  // -------------------------------------------------------------------------------
-struct aiMetadataEntry
-{
+struct aiMetadataEntry {
     aiMetadataType mType;
     aiMetadataType mType;
     void* mData;
     void* mData;
 };
 };
@@ -101,12 +92,13 @@ struct aiMetadataEntry
   * Helper functions to get the aiType enum entry for a type
   * Helper functions to get the aiType enum entry for a type
   */
   */
  // -------------------------------------------------------------------------------
  // -------------------------------------------------------------------------------
-inline aiMetadataType GetAiType( bool ) { return AI_BOOL; }
-inline aiMetadataType GetAiType( int32_t ) { return AI_INT32; }
-inline aiMetadataType GetAiType( uint64_t ) { return AI_UINT64; }
-inline aiMetadataType GetAiType( float ) { return AI_FLOAT; }
-inline aiMetadataType GetAiType( double ) { return AI_DOUBLE; }
-inline aiMetadataType GetAiType( aiString ) { return AI_AISTRING; }
+
+inline aiMetadataType GetAiType( bool )       { return AI_BOOL; }
+inline aiMetadataType GetAiType( int32_t )    { return AI_INT32; }
+inline aiMetadataType GetAiType( uint64_t )   { return AI_UINT64; }
+inline aiMetadataType GetAiType( float )      { return AI_FLOAT; }
+inline aiMetadataType GetAiType( double )     { return AI_DOUBLE; }
+inline aiMetadataType GetAiType( aiString )   { return AI_AISTRING; }
 inline aiMetadataType GetAiType( aiVector3D ) { return AI_AIVECTOR3D; }
 inline aiMetadataType GetAiType( aiVector3D ) { return AI_AIVECTOR3D; }
 
 
 #endif // __cplusplus
 #endif // __cplusplus
@@ -118,8 +110,7 @@ inline aiMetadataType GetAiType( aiVector3D ) { return AI_AIVECTOR3D; }
   * Metadata is a key-value store using string keys and values.
   * Metadata is a key-value store using string keys and values.
   */
   */
  // -------------------------------------------------------------------------------
  // -------------------------------------------------------------------------------
-struct aiMetadata
-{
+struct aiMetadata {
     /** Length of the mKeys and mValues arrays, respectively */
     /** Length of the mKeys and mValues arrays, respectively */
     unsigned int mNumProperties;
     unsigned int mNumProperties;
 
 
@@ -132,28 +123,28 @@ struct aiMetadata
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 
 
-    /** Constructor */
+    /** 
+     *  @brief  The default constructor, set all members to zero by default.
+     */
     aiMetadata()
     aiMetadata()
-        // set all members to zero by default
-        : mNumProperties(0)
-        , mKeys(NULL)
-        , mValues(NULL)
-    {}
+    : mNumProperties(0)
+    , mKeys(NULL)
+    , mValues(NULL) {
+        // empty
+    }
 
 
 
 
-    /** Destructor */
-    ~aiMetadata()
-    {
-        delete[] mKeys;
+    /** 
+     *  @brief The destructor.
+     */
+    ~aiMetadata() {
+        delete [] mKeys;
         mKeys = NULL;
         mKeys = NULL;
-        if (mValues)
-        {
+        if (mValues) {
             // Delete each metadata entry
             // Delete each metadata entry
-            for (unsigned i=0; i<mNumProperties; ++i)
-            {
+            for (unsigned i=0; i<mNumProperties; ++i) {
                 void* data = mValues[i].mData;
                 void* data = mValues[i].mData;
-                switch (mValues[i].mType)
-                {
+                switch (mValues[i].mType) {
                 case AI_BOOL:
                 case AI_BOOL:
                     delete static_cast<bool*>(data);
                     delete static_cast<bool*>(data);
                     break;
                     break;
@@ -179,7 +170,6 @@ struct aiMetadata
                 case FORCE_32BIT:
                 case FORCE_32BIT:
 #endif
 #endif
                 default:
                 default:
-                    assert(false);
                     break;
                     break;
                 }
                 }
             }
             }
@@ -190,13 +180,36 @@ struct aiMetadata
         }
         }
     }
     }
 
 
+    /**
+     *  @brief Allocates property fields + keys.
+     *  @param  numProperties   Number of requested properties.
+     */
+    static inline
+    aiMetadata *Alloc( unsigned int numProperties ) {
+        if ( 0 == numProperties ) {
+            return nullptr;
+        }
+
+        aiMetadata *data = new aiMetadata;
+        data->mNumProperties = numProperties;
+        data->mKeys = new aiString[ data->mNumProperties ]();
+        data->mValues = new aiMetadataEntry[ data->mNumProperties ]();
 
 
+        return data;
+    }
 
 
     template<typename T>
     template<typename T>
-    inline void Set( unsigned index, const std::string& key, const T& value )
-    {
+    inline 
+    bool Set( unsigned index, const std::string& key, const T& value ) {
         // In range assertion
         // In range assertion
-        assert(index < mNumProperties);
+        if ( index >= mNumProperties ) {
+            return false;
+        }
+
+        // Ensure that we have a valid key.
+        if ( key.empty() ) {
+            return false;
+        }
 
 
         // Set metadata key
         // Set metadata key
         mKeys[index] = key;
         mKeys[index] = key;
@@ -205,13 +218,17 @@ struct aiMetadata
         mValues[index].mType = GetAiType(value);
         mValues[index].mType = GetAiType(value);
         // Copy the given value to the dynamic storage
         // Copy the given value to the dynamic storage
         mValues[index].mData = new T(value);
         mValues[index].mData = new T(value);
+
+        return true;
     }
     }
 
 
     template<typename T>
     template<typename T>
-    inline bool Get( unsigned index, T& value )
-    {
+    inline 
+    bool Get( unsigned index, T& value ) {
         // In range assertion
         // In range assertion
-        assert(index < mNumProperties);
+        if ( index >= mNumProperties ) {
+            return false;
+        }
 
 
         // Return false if the output data type does
         // Return false if the output data type does
         // not match the found value's data type
         // not match the found value's data type
@@ -222,16 +239,19 @@ struct aiMetadata
         // Otherwise, output the found value and
         // Otherwise, output the found value and
         // return true
         // return true
         value = *static_cast<T*>(mValues[index].mData);
         value = *static_cast<T*>(mValues[index].mData);
+
         return true;
         return true;
     }
     }
 
 
     template<typename T>
     template<typename T>
-    inline bool Get( const aiString& key, T& value )
-    {
+    inline 
+    bool Get( const aiString& key, T& value ) {
         // Search for the given key
         // Search for the given key
-        for (unsigned i=0; i<mNumProperties; ++i)
-            if (mKeys[i]==key)
-                return Get(i, value);
+        for ( unsigned int i = 0; i < mNumProperties; ++i ) {
+            if ( mKeys[ i ] == key ) {
+                return Get( i, value );
+            }
+        }
         return false;
         return false;
     }
     }
 
 
@@ -240,18 +260,18 @@ struct aiMetadata
         return Get(aiString(key), value);
         return Get(aiString(key), value);
     }
     }
 
 
-	/// \fn inline bool Get(size_t pIndex, const aiString*& pKey, const aiMetadataEntry*& pEntry)
 	/// Return metadata entry for analyzing it by user.
 	/// Return metadata entry for analyzing it by user.
 	/// \param [in] pIndex - index of the entry.
 	/// \param [in] pIndex - index of the entry.
 	/// \param [out] pKey - pointer to the key value.
 	/// \param [out] pKey - pointer to the key value.
 	/// \param [out] pEntry - pointer to the entry: type and value.
 	/// \param [out] pEntry - pointer to the entry: type and value.
 	/// \return false - if pIndex is out of range, else - true.
 	/// \return false - if pIndex is out of range, else - true.
-	inline bool Get(size_t pIndex, const aiString*& pKey, const aiMetadataEntry*& pEntry)
-	{
-		if(pIndex >= mNumProperties) return false;
+	inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) {
+        if ( index >= mNumProperties ) {
+            return false;
+        }
 
 
-		pKey = &mKeys[pIndex];
-		pEntry = &mValues[pIndex];
+		key = &mKeys[index];
+		entry = &mValues[index];
 
 
 		return true;
 		return true;
 	}
 	}

+ 1 - 1
include/assimp/types.h

@@ -109,7 +109,7 @@ extern "C" {
 
 
 /** Maximum dimension for strings, ASSIMP strings are zero terminated. */
 /** Maximum dimension for strings, ASSIMP strings are zero terminated. */
 #ifdef __cplusplus
 #ifdef __cplusplus
-const size_t MAXLEN = 1024;
+static const size_t MAXLEN = 1024;
 #else
 #else
 #   define MAXLEN 1024
 #   define MAXLEN 1024
 #endif
 #endif

+ 1 - 1
scripts/BlenderImporter/BlenderScene.cpp.template

@@ -2,7 +2,7 @@
 Open Asset Import Library (ASSIMP)
 Open Asset Import Library (ASSIMP)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2010, ASSIMP Development Team
+Copyright (c) 2006-2016, ASSIMP Development Team
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms, 
 Redistribution and use of this software in source and binary forms, 

+ 1 - 1
scripts/BlenderImporter/BlenderSceneGen.h.template

@@ -2,7 +2,7 @@
 Open Asset Import Library (ASSIMP)
 Open Asset Import Library (ASSIMP)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2010, ASSIMP Development Team
+Copyright (c) 2006-2016, ASSIMP Development Team
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms, 
 Redistribution and use of this software in source and binary forms, 

+ 1 - 1
scripts/BlenderImporter/genblenddna.py

@@ -5,7 +5,7 @@
 # Open Asset Import Library (ASSIMP)
 # Open Asset Import Library (ASSIMP)
 # ---------------------------------------------------------------------------
 # ---------------------------------------------------------------------------
 #
 #
-# Copyright (c) 2006-2013, ASSIMP Development Team
+# Copyright (c) 2006-2016, ASSIMP Development Team
 #
 #
 # All rights reserved.
 # All rights reserved.
 #
 #

+ 1 - 0
test/CMakeLists.txt

@@ -79,6 +79,7 @@ SET( TEST_SRCS
   unit/utMaterialSystem.cpp
   unit/utMaterialSystem.cpp
   unit/utMatrix3x3.cpp
   unit/utMatrix3x3.cpp
   unit/utMatrix4x4.cpp
   unit/utMatrix4x4.cpp
+  unit/utMetadata.cpp
   unit/SceneDiffer.h
   unit/SceneDiffer.h
   unit/SceneDiffer.cpp
   unit/SceneDiffer.cpp
   unit/utObjImportExport.cpp
   unit/utObjImportExport.cpp

BIN
test/regression/db.zip


+ 5 - 2
test/unit/utBlenderIntermediate.cpp

@@ -52,10 +52,13 @@ class BlenderIntermediateTest : public ::testing::Test {
     // empty
     // empty
 };
 };
 
 
+#define NAME_1 "name1"
+#define NAME_2 "name2"
+
 TEST_F( BlenderIntermediateTest,ConversionData_ObjectCompareTest ) {
 TEST_F( BlenderIntermediateTest,ConversionData_ObjectCompareTest ) {
     Object obj1, obj2;
     Object obj1, obj2;
-    strncpy( obj1.id.name, "name1", 5 );
-    strncpy( obj2.id.name, "name2", 5 );
+    strncpy( obj1.id.name, NAME_1, sizeof(NAME_1) );
+    strncpy( obj2.id.name, NAME_2, sizeof(NAME_2) );
     Blender::ObjectCompare cmp_false;
     Blender::ObjectCompare cmp_false;
     bool res( cmp_false( &obj1, &obj2 ) );
     bool res( cmp_false( &obj1, &obj2 ) );
     EXPECT_FALSE( res );
     EXPECT_FALSE( res );

+ 3 - 3
test/unit/utMatrix4x4.cpp

@@ -43,17 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
-class utMatrix4x4Test : public ::testing::Test {
+class utMatrix4x4 : public ::testing::Test {
 
 
 };
 };
 
 
-TEST_F( utMatrix4x4Test, badIndexOperatorTest ) {
+TEST_F( utMatrix4x4, badIndexOperatorTest ) {
     aiMatrix4x4 m;
     aiMatrix4x4 m;
     ai_real *a0 = m[ 4 ];
     ai_real *a0 = m[ 4 ];
     EXPECT_EQ( NULL, a0 );
     EXPECT_EQ( NULL, a0 );
 }
 }
 
 
-TEST_F( utMatrix4x4Test, indexOperatorTest ) {
+TEST_F( utMatrix4x4, indexOperatorTest ) {
     aiMatrix4x4 m;
     aiMatrix4x4 m;
     ai_real *a0 = m[ 0 ];
     ai_real *a0 = m[ 0 ];
     EXPECT_FLOAT_EQ( 1.0, *a0 );
     EXPECT_FLOAT_EQ( 1.0, *a0 );

+ 179 - 0
test/unit/utMetadata.cpp

@@ -0,0 +1,179 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2016, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "UnitTestPCH.h"
+
+#include <assimp/metadata.h>
+
+using namespace ::Assimp;
+
+class utMetadata: public ::testing::Test {
+protected:
+    aiMetadata *m_data;
+
+    virtual void SetUp() {
+        m_data = nullptr;
+    }
+
+    virtual void TearDown() {
+        delete m_data;
+    }
+
+};
+
+TEST_F( utMetadata, creationTest ) {
+    bool ok( true );
+    try {
+        aiMetadata data;
+    } catch ( ... ) {
+        ok = false;
+    }
+    EXPECT_TRUE( ok );
+}
+
+TEST_F( utMetadata, allocTest ) {
+    aiMetadata *data = aiMetadata::Alloc( 0 );
+    EXPECT_EQ( nullptr, data );
+
+    data = aiMetadata::Alloc( 1 );
+    EXPECT_NE( nullptr, data );
+    EXPECT_EQ( 1, data->mNumProperties );
+    EXPECT_NE( nullptr, data->mKeys );
+    EXPECT_NE( nullptr, data->mValues );
+}
+
+TEST_F( utMetadata, get_set_pod_Test ) {
+    m_data = aiMetadata::Alloc( 5 );
+
+    // int, 32 bit
+    unsigned int index( 0 );
+    bool success( false );
+    const std::string key_int = "test_int";
+    success = m_data->Set( index, key_int, 1 );
+    EXPECT_TRUE( success );
+    success = m_data->Set( index + 10, key_int, 1 );
+    EXPECT_FALSE( success );
+
+    // unsigned int, 64 bit
+    index++;
+    const std::string key_uint = "test_uint";
+    success = m_data->Set<uint64_t>( index, key_uint, 1UL );
+    EXPECT_TRUE( success );
+    uint64_t result_uint( 0 );
+    success = m_data->Get( key_uint, result_uint );
+    EXPECT_TRUE( success );
+    EXPECT_EQ( 1UL, result_uint );
+
+    // bool
+    index++;
+    const std::string key_bool = "test_bool";
+    success = m_data->Set( index, key_bool, true );
+    EXPECT_TRUE( success );
+    bool result_bool( false );
+    success = m_data->Get( key_bool, result_bool );
+    EXPECT_TRUE( success );
+    EXPECT_EQ( true, result_bool );
+
+    // float
+    index++;
+    const std::string key_float = "test_float";
+    float fVal = 2.0f;
+    success = m_data->Set( index, key_float, fVal );
+    EXPECT_TRUE( success );
+    float result_float( 0.0f );
+    success = m_data->Get( key_float, result_float );
+    EXPECT_TRUE( success );
+    EXPECT_FLOAT_EQ( 2.0f, result_float );
+
+    // double
+    index++;
+    const std::string key_double = "test_double";
+    double dVal = 3.0;
+    success = m_data->Set( index, key_double, dVal );
+    EXPECT_TRUE( success );
+    double result_double( 0.0 );
+    success = m_data->Get( key_double, result_double );
+    EXPECT_TRUE( success );
+    EXPECT_DOUBLE_EQ( 3.0, result_double );
+
+    // error
+    int result;
+    success = m_data->Get( "bla", result );
+    EXPECT_FALSE( success );
+}
+
+TEST_F( utMetadata, get_set_string_Test ) {
+    m_data = aiMetadata::Alloc( 1 );
+
+    unsigned int index( 0 );
+    bool success( false );
+    const std::string key = "test";
+    success = m_data->Set( index, key, aiString( std::string( "test" ) ) );
+    EXPECT_TRUE( success );
+
+    success = m_data->Set( index+10, key, aiString( std::string( "test" ) ) );
+    EXPECT_FALSE( success );
+
+    aiString result;
+    success = m_data->Get( key, result );
+    EXPECT_EQ( aiString( std::string( "test" ) ), result );
+    EXPECT_TRUE( success );
+
+    success = m_data->Get( "bla", result );
+    EXPECT_FALSE( success );
+}
+
+TEST_F( utMetadata, get_set_aiVector3D_Test ) {
+    m_data = aiMetadata::Alloc( 1 );
+
+    unsigned int index( 0 );
+    bool success( false );
+    const std::string key = "test";
+    aiVector3D vec( 1, 2, 3 );
+
+    success = m_data->Set( index, key, vec );
+    EXPECT_TRUE( success );
+
+    aiVector3D result( 0, 0, 0 );
+    success = m_data->Get( key, result );
+    EXPECT_EQ( vec, result );
+    EXPECT_TRUE( success );
+}

+ 2 - 0
test/unit/utObjImportExport.cpp

@@ -186,4 +186,6 @@ TEST_F( utObjImportExport, obj_import_test ) {
     SceneDiffer differ;
     SceneDiffer differ;
     EXPECT_TRUE( differ.isEqual( expected, scene ) );
     EXPECT_TRUE( differ.isEqual( expected, scene ) );
     differ.showReport();
     differ.showReport();
+
+    m_im->FreeScene();
 }
 }

+ 40 - 0
tools/coverity/assimp_modeling.cpp

@@ -0,0 +1,40 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+//