Browse Source

Merge branch 'master' into remove-useless-scaling-prototype

Kim Kulling 4 years ago
parent
commit
9c44c0ab2b
66 changed files with 1337 additions and 472 deletions
  1. 1 1
      Readme.md
  2. 1 1
      code/AssetLib/3DS/3DSConverter.cpp
  3. 3 2
      code/AssetLib/3DS/3DSExporter.cpp
  4. 3 13
      code/AssetLib/3DS/3DSHelper.h
  5. 4 4
      code/AssetLib/3DS/3DSLoader.cpp
  6. 53 50
      code/AssetLib/3MF/3MFXmlTags.h
  7. 26 11
      code/AssetLib/3MF/D3MFExporter.cpp
  8. 79 78
      code/AssetLib/3MF/D3MFImporter.cpp
  9. 4 4
      code/AssetLib/3MF/D3MFOpcPackage.cpp
  10. 2 2
      code/AssetLib/AC/ACLoader.h
  11. 0 4
      code/AssetLib/AMF/AMFImporter.cpp
  12. 0 1
      code/AssetLib/AMF/AMFImporter.hpp
  13. 2 2
      code/AssetLib/AMF/AMFImporter_Postprocess.cpp
  14. 1 1
      code/AssetLib/ASE/ASEParser.cpp
  15. 1 7
      code/AssetLib/Blender/BlenderLoader.cpp
  16. 0 1
      code/AssetLib/Blender/BlenderLoader.h
  17. 2 2
      code/AssetLib/Collada/ColladaLoader.cpp
  18. 1 1
      code/AssetLib/FBX/FBXMeshGeometry.cpp
  19. 4 4
      code/AssetLib/FBX/FBXParser.cpp
  20. 1 1
      code/AssetLib/FBX/FBXProperties.cpp
  21. 2 2
      code/AssetLib/IFC/IFCLoader.cpp
  22. 1 1
      code/AssetLib/Irr/IRRLoader.cpp
  23. 1 1
      code/AssetLib/Irr/IRRMeshLoader.cpp
  24. 1 1
      code/AssetLib/LWO/LWOFileData.h
  25. 1 1
      code/AssetLib/LWS/LWSLoader.h
  26. 2 3
      code/AssetLib/M3D/M3DImporter.cpp
  27. 1 1
      code/AssetLib/MD2/MD2NormalTable.h
  28. 1 1
      code/AssetLib/MDC/MDCNormalTable.h
  29. 1 1
      code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp
  30. 1 1
      code/AssetLib/MMD/MMDImporter.cpp
  31. 1 1
      code/AssetLib/MMD/MMDPmxParser.cpp
  32. 1 1
      code/AssetLib/OpenGEX/OpenGEXImporter.cpp
  33. 1 1
      code/AssetLib/OpenGEX/OpenGEXImporter.h
  34. 1 1
      code/AssetLib/Q3BSP/Q3BSPFileData.h
  35. 9 9
      code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp
  36. 1 1
      code/AssetLib/X/XFileHelper.h
  37. 0 4
      code/AssetLib/X3D/X3DImporter.cpp
  38. 0 1
      code/AssetLib/X3D/X3DImporter.hpp
  39. 1 1
      code/AssetLib/XGL/XGLLoader.cpp
  40. 1 1
      code/AssetLib/glTF/glTFAsset.h
  41. 1 1
      code/AssetLib/glTF2/glTF2Asset.h
  42. 25 2
      code/AssetLib/glTF2/glTF2Asset.inl
  43. 3 3
      code/AssetLib/glTF2/glTF2Importer.cpp
  44. 2 2
      code/CApi/CInterfaceIOWrapper.cpp
  45. 2 2
      code/Common/BaseImporter.cpp
  46. 4 2
      code/Common/DefaultIOStream.cpp
  47. 1 1
      code/Common/FileSystemFilter.h
  48. 3 3
      code/Common/Importer.cpp
  49. 4 2
      code/Common/SceneCombiner.cpp
  50. 1 1
      code/Common/scene.cpp
  51. 1 1
      code/PostProcessing/RemoveRedundantMaterials.h
  52. 3 1
      code/PostProcessing/SortByPTypeProcess.cpp
  53. 0 58
      contrib/zip/.gitignore
  54. 29 15
      contrib/zip/CMakeLists.txt
  55. 132 17
      contrib/zip/README.md
  56. 45 29
      contrib/zip/src/miniz.h
  57. 704 63
      contrib/zip/src/zip.c
  58. 109 27
      contrib/zip/src/zip.h
  59. 34 7
      contrib/zip/test/CMakeLists.txt
  60. 1 0
      doc/Fileformats.md
  61. 1 1
      include/assimp/DefaultIOStream.h
  62. 1 1
      include/assimp/IOSystem.hpp
  63. 1 1
      include/assimp/Importer.hpp
  64. 1 1
      include/assimp/XmlParser.h
  65. 8 3
      include/assimp/postprocess.h
  66. 5 4
      tools/assimp_cmd/ImageExtractor.cpp

+ 1 - 1
Readme.md

@@ -8,10 +8,10 @@ A library to import and export various 3d-model-formats including scene-post-pro
   <img alt="Coverity Scan Build Status"
        src="https://scan.coverity.com/projects/5607/badge.svg"/>
 </a>
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
 [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
 [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
-[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
 [![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
 <br>
 

+ 1 - 1
code/AssetLib/3DS/3DSConverter.cpp

@@ -212,7 +212,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
         mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
 
         // Be sure this is only done for the first material
-        mBackgroundImage = std::string("");
+        mBackgroundImage = std::string();
     }
 
     // At first add the base ambient color of the scene to the material

+ 3 - 2
code/AssetLib/3DS/3DSExporter.cpp

@@ -102,13 +102,14 @@ private:
 // preserves the mesh's given name if it has one. |index| is the index
 // of the mesh in |aiScene::mMeshes|.
 std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) {
-    static const std::string underscore = "_";
+    static const char underscore = '_';
     char postfix[10] = { 0 };
     ASSIMP_itoa10(postfix, index);
 
     std::string result = node.mName.C_Str();
     if (mesh.mName.length > 0) {
-        result += underscore + mesh.mName.C_Str();
+        result += underscore;
+        result += mesh.mName.C_Str();
     }
     return result + underscore + postfix;
 }

+ 3 - 13
code/AssetLib/3DS/3DSHelper.h

@@ -61,20 +61,10 @@ namespace D3DS {
 #include <assimp/Compiler/pushpack1.h>
 
 // ---------------------------------------------------------------------------
-/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks
-*  and data structures.
+/** Defines chunks and data structures.
 */
-class Discreet3DS {
-private:
-    Discreet3DS() AI_NO_EXCEPT {
-        // empty
-    }
-
-    ~Discreet3DS() {
-        // empty
-    }
+namespace Discreet3DS {
 
-public:
     //! data structure for a single chunk in a .3ds file
     struct Chunk {
         uint16_t Flag;
@@ -314,7 +304,7 @@ public:
         // camera sub-chunks
         CHUNK_CAM_RANGES = 0x4720
     };
-};
+}
 
 // ---------------------------------------------------------------------------
 /** Helper structure representing a 3ds mesh face */

+ 4 - 4
code/AssetLib/3DS/3DSLoader.cpp

@@ -164,7 +164,7 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
     mRootNode->mHierarchyIndex = -1;
     mRootNode->mParent = nullptr;
     mMasterScale = 1.0f;
-    mBackgroundImage = "";
+    mBackgroundImage = std::string();
     bHasBG = false;
     bIsPrj = false;
 
@@ -981,9 +981,9 @@ void Discreet3DSImporter::ParseMeshChunk() {
         mMesh.mMat.a3 = stream->GetF4();
         mMesh.mMat.b3 = stream->GetF4();
         mMesh.mMat.c3 = stream->GetF4();
-        mMesh.mMat.d1 = stream->GetF4();
-        mMesh.mMat.d2 = stream->GetF4();
-        mMesh.mMat.d3 = stream->GetF4();
+        mMesh.mMat.a4 = stream->GetF4();
+        mMesh.mMat.b4 = stream->GetF4();
+        mMesh.mMat.c4 = stream->GetF4();
     } break;
 
     case Discreet3DS::CHUNK_MAPLIST: {

+ 53 - 50
code/AssetLib/3MF/3MFXmlTags.h

@@ -44,63 +44,66 @@ namespace Assimp {
 namespace D3MF {
 
 namespace XmlTag {
+    // Root tag
+    const char* const RootTag = "3MF";
+
     // Meta-data
-    static const std::string meta = "metadata";
-    static const std::string meta_name = "name";
+    const char* const meta = "metadata";
+    const char* const meta_name = "name";
 
     // Model-data specific tags
-    static const std::string model = "model";
-    static const std::string model_unit = "unit";
-    static const std::string metadata = "metadata";
-    static const std::string resources = "resources";
-    static const std::string object = "object";
-    static const std::string mesh = "mesh";
-    static const std::string components = "components";
-    static const std::string component = "component";
-    static const std::string vertices = "vertices";
-    static const std::string vertex = "vertex";
-    static const std::string triangles = "triangles";
-    static const std::string triangle = "triangle";
-    static const std::string x = "x";
-    static const std::string y = "y";
-    static const std::string z = "z";
-    static const std::string v1 = "v1";
-    static const std::string v2 = "v2";
-    static const std::string v3 = "v3";
-    static const std::string id = "id";
-    static const std::string pid = "pid";
-    static const std::string pindex = "pindex";
-    static const std::string p1 = "p1";
-    static const std::string name = "name";
-    static const std::string type = "type";
-    static const std::string build = "build";
-    static const std::string item = "item";
-    static const std::string objectid = "objectid";
-    static const std::string transform = "transform";
+    const char* const model = "model";
+    const char* const model_unit = "unit";
+    const char* const metadata = "metadata";
+    const char* const resources = "resources";
+    const char* const object = "object";
+    const char* const mesh = "mesh";
+    const char* const components = "components";
+    const char* const component = "component";
+    const char* const vertices = "vertices";
+    const char* const vertex = "vertex";
+    const char* const triangles = "triangles";
+    const char* const triangle = "triangle";
+    const char* const x = "x";
+    const char* const y = "y";
+    const char* const z = "z";
+    const char* const v1 = "v1";
+    const char* const v2 = "v2";
+    const char* const v3 = "v3";
+    const char* const id = "id";
+    const char* const pid = "pid";
+    const char* const pindex = "pindex";
+    const char* const p1 = "p1";
+    const char* const name = "name";
+    const char* const type = "type";
+    const char* const build = "build";
+    const char* const item = "item";
+    const char* const objectid = "objectid";
+    const char* const transform = "transform";
 
     // Material definitions
-    static const std::string basematerials = "basematerials";
-    static const std::string basematerials_id = "id";
-    static const std::string basematerials_base = "base";
-    static const std::string basematerials_name = "name";
-    static const std::string basematerials_displaycolor = "displaycolor";
+    const char* const basematerials = "basematerials";
+    const char* const basematerials_id = "id";
+    const char* const basematerials_base = "base";
+    const char* const basematerials_name = "name";
+    const char* const basematerials_displaycolor = "displaycolor";
 
     // Meta info tags
-    static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
-    static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
-    static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
-    static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
-    static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships";
-    static const std::string RELS_RELATIONSHIP_NODE = "Relationship";
-    static const std::string RELS_ATTRIB_TARGET = "Target";
-    static const std::string RELS_ATTRIB_TYPE = "Type";
-    static const std::string RELS_ATTRIB_ID = "Id";
-    static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
-    static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
-    static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
-    static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
-    static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
-}
+    const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
+    const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
+    const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
+    const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
+    const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships";
+    const char* const RELS_RELATIONSHIP_NODE = "Relationship";
+    const char* const RELS_ATTRIB_TARGET = "Target";
+    const char* const RELS_ATTRIB_TYPE = "Type";
+    const char* const RELS_ATTRIB_ID = "Id";
+    const char* const PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
+    const char* const PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
+    const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
+    const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
+    const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
+    }
 
 } // Namespace D3MF
 } // Namespace Assimp

+ 26 - 11
code/AssetLib/3MF/D3MFExporter.cpp

@@ -307,18 +307,26 @@ void D3MFExporter::writeMesh(aiMesh *mesh) {
         return;
     }
 
-    mModelOutput << "<" << XmlTag::mesh << ">" << std::endl;
-    mModelOutput << "<" << XmlTag::vertices << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::mesh
+                 << ">" << "\n";
+    mModelOutput << "<"
+                 << XmlTag::vertices
+                 << ">" << "\n";
     for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
         writeVertex(mesh->mVertices[i]);
     }
-    mModelOutput << "</" << XmlTag::vertices << ">" << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::vertices << ">"
+                 << "\n";
 
     const unsigned int matIdx(mesh->mMaterialIndex);
 
     writeFaces(mesh, matIdx);
 
-    mModelOutput << "</" << XmlTag::mesh << ">" << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::mesh << ">"
+                 << "\n";
 }
 
 void D3MFExporter::writeVertex(const aiVector3D &pos) {
@@ -334,27 +342,34 @@ void D3MFExporter::writeFaces(aiMesh *mesh, unsigned int matIdx) {
     if (!mesh->HasFaces()) {
         return;
     }
-    mModelOutput << "<" << XmlTag::triangles << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::triangles << ">"
+                 << "\n";
     for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
         aiFace &currentFace = mesh->mFaces[i];
         mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\""
                      << currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2]
                      << "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />";
-        mModelOutput << std::endl;
+        mModelOutput << "\n";
     }
-    mModelOutput << "</" << XmlTag::triangles << ">";
-    mModelOutput << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::triangles
+                 << ">";
+    mModelOutput << "\n";
 }
 
 void D3MFExporter::writeBuild() {
-    mModelOutput << "<" << XmlTag::build << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::build
+                 << ">"
+                 << "\n";
 
     for (size_t i = 0; i < mBuildItems.size(); ++i) {
         mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>";
-        mModelOutput << std::endl;
+        mModelOutput << "\n";
     }
     mModelOutput << "</" << XmlTag::build << ">";
-    mModelOutput << std::endl;
+    mModelOutput << "\n";
 }
 
 void D3MFExporter::zipContentType(const std::string &filename) {

+ 79 - 78
code/AssetLib/3MF/D3MFImporter.cpp

@@ -72,32 +72,39 @@ enum class ResourceType {
     RT_Unknown
 }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
 
-class Resource
-{
+class Resource {
 public:
-    Resource(int id) :
-            mId(id) {}
+    int mId;
 
-    virtual ~Resource() {}
+    Resource(int id) :
+            mId(id) {
+        // empty
+    }
 
-    int mId;
+    virtual ~Resource() {
+        // empty
+    }
 
-    virtual ResourceType getType() {
+    virtual ResourceType getType() const {
         return ResourceType::RT_Unknown;
     }
 };
 
 class BaseMaterials : public Resource {
 public:
+    std::vector<aiMaterial *> mMaterials;
+    std::vector<unsigned int> mMaterialIndex;
+
     BaseMaterials(int id) :
             Resource(id),
             mMaterials(),
-            mMaterialIndex() {}
+            mMaterialIndex() {
+        // empty
+    }
 
-    std::vector<aiMaterial *> mMaterials;
-    std::vector<unsigned int> mMaterialIndex;
+    ~BaseMaterials() = default;
 
-    virtual ResourceType getType() {
+    ResourceType getType() const override {
         return ResourceType::RT_BaseMaterials;
     }
 };
@@ -109,24 +116,26 @@ struct Component {
 
 class Object : public Resource {
 public:
-    std::vector<aiMesh*> mMeshes;
+    std::vector<aiMesh *> mMeshes;
     std::vector<unsigned int> mMeshIndex;
     std::vector<Component> mComponents;
     std::string mName;
 
     Object(int id) :
             Resource(id),
-            mName(std::string("Object_") + ai_to_string(id)) {}
+            mName(std::string("Object_") + ai_to_string(id)) {
+        // empty
+    }
 
-    virtual ResourceType getType() {
+    ~Object() = default;
+
+    ResourceType getType() const override {
         return ResourceType::RT_Object;
     }
 };
 
-
 class XmlSerializer {
 public:
-
     XmlSerializer(XmlParser *xmlParser) :
             mResourcesDictionnary(),
             mMaterialCount(0),
@@ -136,7 +145,7 @@ public:
     }
 
     ~XmlSerializer() {
-        for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+        for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
             delete it->second;
         }
     }
@@ -146,28 +155,27 @@ public:
             return;
         }
 
-        scene->mRootNode = new aiNode("3MF");
+        scene->mRootNode = new aiNode(XmlTag::RootTag);
 
-        XmlNode node = mXmlParser->getRootNode().child("model");
+        XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
         if (node.empty()) {
             return;
         }
-        XmlNode resNode = node.child("resources");
-        for (XmlNode currentNode = resNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+        XmlNode resNode = node.child(XmlTag::resources);
+        for (auto &currentNode : resNode.children()) {
             const std::string &currentNodeName = currentNode.name();
-            if (currentNodeName == D3MF::XmlTag::object) {
-                ReadObject(currentNode);;
-            } else if (currentNodeName == D3MF::XmlTag::basematerials) {
+            if (currentNodeName == XmlTag::object) {
+                ReadObject(currentNode);
+            } else if (currentNodeName == XmlTag::basematerials) {
                 ReadBaseMaterials(currentNode);
-            } else if (currentNodeName == D3MF::XmlTag::meta) {
+            } else if (currentNodeName == XmlTag::meta) {
                 ReadMetadata(currentNode);
             }
         }
 
-        XmlNode buildNode = node.child("build");
-        for (XmlNode currentNode = buildNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+        for (auto &currentNode : resNode.children()) {
             const std::string &currentNodeName = currentNode.name();
-            if (currentNodeName == D3MF::XmlTag::item) {
+            if (currentNodeName == XmlTag::item) {
                 int objectId = -1;
                 std::string transformationMatrixStr;
                 aiMatrix4x4 transformationMatrix;
@@ -186,7 +194,6 @@ public:
             }
         }
 
-
         // import the metadata
         if (!mMetaData.empty()) {
             const size_t numMeta(mMetaData.size());
@@ -201,22 +208,21 @@ public:
         scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
         if (scene->mNumMeshes != 0) {
             scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
-            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
                 if (it->second->getType() == ResourceType::RT_Object) {
-                    Object *obj = static_cast<Object*>(it->second);
+                    Object *obj = static_cast<Object *>(it->second);
                     for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
                         scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
                     }
                 }
             }
         }
-        
 
         // import the materials
-        scene->mNumMaterials = static_cast<unsigned int>(mMaterialCount);
+        scene->mNumMaterials = mMaterialCount;
         if (scene->mNumMaterials != 0) {
             scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
-            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
                 if (it->second->getType() == ResourceType::RT_BaseMaterials) {
                     BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
                     for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
@@ -228,35 +234,36 @@ public:
     }
 
 private:
+    void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
+        ai_assert(nullptr != obj);
 
-    void addObjectToNode(aiNode* parent, Object* obj, aiMatrix4x4 nodeTransform) {
         aiNode *sceneNode = new aiNode(obj->mName);
         sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
         sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
         std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
 
         sceneNode->mTransformation = nodeTransform;
-
-        parent->addChildren(1, &sceneNode);
+        if (nullptr != parent) {
+            parent->addChildren(1, &sceneNode);
+        }
 
         for (size_t i = 0; i < obj->mComponents.size(); ++i) {
             Component c = obj->mComponents[i];
             auto it = mResourcesDictionnary.find(c.mObjectId);
             if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
-                addObjectToNode(sceneNode, static_cast<Object*>(it->second), c.mTransformation);
+                addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
             }
-            
         }
     }
 
-    bool getNodeAttribute(const XmlNode& node, const std::string& attribute, std::string& value) {
+    bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
         pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
         if (!objectAttribute.empty()) {
             value = objectAttribute.as_string();
             return true;
-        } else {
-            return false;
         }
+
+        return false;
     }
 
     bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
@@ -265,9 +272,9 @@ private:
         if (ret) {
             value = std::atoi(strValue.c_str());
             return true;
-        } else {
-            return false;
-        }
+        } 
+
+        return false;
     }
 
     aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
@@ -287,7 +294,7 @@ private:
             }
         }
         if (currentNumber.size() > 0) {
-            float f = std::stof(currentNumber);
+            const float f = std::stof(currentNumber);
             numbers.push_back(f);
         }
 
@@ -311,29 +318,26 @@ private:
         transformMatrix.b4 = numbers[10];
         transformMatrix.c4 = numbers[11];
         transformMatrix.d4 = 1;
+
         return transformMatrix;
     }
 
     void ReadObject(XmlNode &node) {
         int id = -1, pid = -1, pindex = -1;
-        bool hasId = getNodeAttribute(node, D3MF::XmlTag::id, id);
-        //bool hasType = getNodeAttribute(node, D3MF::XmlTag::type, type); not used currently
-        bool hasPid = getNodeAttribute(node, D3MF::XmlTag::pid, pid);
-        bool hasPindex = getNodeAttribute(node, D3MF::XmlTag::pindex, pindex);
-
-        std::string idStr = ai_to_string(id);
-
+        bool hasId = getNodeAttribute(node, XmlTag::id, id);
+        bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
+        bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
         if (!hasId) {
             return;
         }
 
         Object *obj = new Object(id);
 
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+        for (XmlNode &currentNode : node.children()) {
             const std::string &currentName = currentNode.name();
             if (currentName == D3MF::XmlTag::mesh) {
                 auto mesh = ReadMesh(currentNode);
-                mesh->mName.Set(idStr);
+                mesh->mName.Set(ai_to_string(id));
 
                 if (hasPid) {
                     auto it = mResourcesDictionnary.find(pid);
@@ -347,7 +351,7 @@ private:
                 obj->mMeshIndex.push_back(mMeshCount);
                 mMeshCount++;
             } else if (currentName == D3MF::XmlTag::components) {
-                for (XmlNode currentSubNode = currentNode.first_child(); currentSubNode; currentSubNode = currentSubNode.next_sibling()) {
+                for (XmlNode &currentSubNode : currentNode.children()) {
                     if (currentSubNode.name() == D3MF::XmlTag::component) {
                         int objectId = -1;
                         std::string componentTransformStr;
@@ -369,21 +373,20 @@ private:
     aiMesh *ReadMesh(XmlNode &node) {
         aiMesh *mesh = new aiMesh();
 
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+        for (XmlNode &currentNode : node.children()) {
             const std::string &currentName = currentNode.name();
-            if (currentName == D3MF::XmlTag::vertices) {
+            if (currentName == XmlTag::vertices) {
                 ImportVertices(currentNode, mesh);
-            } else if (currentName == D3MF::XmlTag::triangles) {
+            } else if (currentName == XmlTag::triangles) {
                 ImportTriangles(currentNode, mesh);
             }
-
         }
 
         return mesh;
     }
 
     void ReadMetadata(XmlNode &node) {
-        pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name.c_str());
+        pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
         const std::string name = attribute.as_string();
         const std::string value = node.value();
         if (name.empty()) {
@@ -398,7 +401,7 @@ private:
 
     void ImportVertices(XmlNode &node, aiMesh *mesh) {
         std::vector<aiVector3D> vertices;
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+        for (XmlNode &currentNode : node.children()) {
             const std::string &currentName = currentNode.name();
             if (currentName == D3MF::XmlTag::vertex) {
                 vertices.push_back(ReadVertex(currentNode));
@@ -412,9 +415,9 @@ private:
 
     aiVector3D ReadVertex(XmlNode &node) {
         aiVector3D vertex;
-        vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x.c_str()).as_string(), nullptr);
-        vertex.y = ai_strtof(node.attribute(D3MF::XmlTag::y.c_str()).as_string(), nullptr);
-        vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z.c_str()).as_string(), nullptr);
+        vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x).as_string(), nullptr);
+        vertex.y = ai_strtof(node.attribute(D3MF::XmlTag::y).as_string(), nullptr);
+        vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z).as_string(), nullptr);
 
         return vertex;
     }
@@ -433,8 +436,7 @@ private:
 
                 if (hasPid && hasP1) {
                     auto it = mResourcesDictionnary.find(pid);
-                    if (it != mResourcesDictionnary.end())
-                    {
+                    if (it != mResourcesDictionnary.end()) {
                         if (it->second->getType() == ResourceType::RT_BaseMaterials) {
                             BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
                             mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
@@ -457,9 +459,9 @@ private:
 
         face.mNumIndices = 3;
         face.mIndices = new unsigned int[face.mNumIndices];
-        face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v1.c_str()).as_string()));
-        face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v2.c_str()).as_string()));
-        face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v3.c_str()).as_string()));
+        face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
+        face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
+        face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
 
         return face;
     }
@@ -467,11 +469,10 @@ private:
     void ReadBaseMaterials(XmlNode &node) {
         int id = -1;
         if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
-            BaseMaterials* baseMaterials = new BaseMaterials(id);
+            BaseMaterials *baseMaterials = new BaseMaterials(id);
 
-            for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling())
-            {
-                if (currentNode.name() == D3MF::XmlTag::basematerials_base) {
+            for (XmlNode &currentNode : node.children()) {
+                if (currentNode.name() == XmlTag::basematerials_base) {
                     baseMaterials->mMaterialIndex.push_back(mMaterialCount);
                     baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
                     mMaterialCount++;
@@ -488,7 +489,7 @@ private:
         }
 
         //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
-        const size_t len(strlen(color));
+        const size_t len = strlen(color);
         if (9 != len && 7 != len) {
             return false;
         }
@@ -517,7 +518,7 @@ private:
     }
 
     void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
-        const char *color = node.attribute(D3MF::XmlTag::basematerials_displaycolor.c_str()).as_string();
+        const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
         aiColor4D diffuse;
         if (parseColor(color, diffuse)) {
             mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
@@ -531,7 +532,7 @@ private:
         bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
 
         std::string stdMaterialName;
-        std::string strId(ai_to_string(basematerialsId));
+        const std::string strId(ai_to_string(basematerialsId));
         stdMaterialName += "id";
         stdMaterialName += strId;
         stdMaterialName += "_";
@@ -556,7 +557,7 @@ private:
         std::string value;
     };
     std::vector<MetaEntry> mMetaData;
-    std::map<unsigned int, Resource*> mResourcesDictionnary;
+    std::map<unsigned int, Resource *> mResourcesDictionnary;
     unsigned int mMaterialCount, mMeshCount;
     XmlParser *mXmlParser;
 };

+ 4 - 4
code/AssetLib/3MF/D3MFOpcPackage.cpp

@@ -103,9 +103,9 @@ public:
             std::string name = currentNode.name();
             if (name == "Relationship") {
                 OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
-                relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID.c_str()).as_string();
-                relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE.c_str()).as_string();
-                relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET.c_str()).as_string();
+                relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
+                relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
+                relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
                 if (validateRels(relPtr)) {
                     m_relationShips.push_back(relPtr);
                 }
@@ -188,7 +188,7 @@ bool D3MFOpcPackage::validate() {
 std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
     XmlParser xmlParser;
     if (!xmlParser.parse(stream)) {
-        return "";
+        return std::string();
     }
 
     OpcPackageRelationshipReader reader(xmlParser);

+ 2 - 2
code/AssetLib/AC/ACLoader.h

@@ -123,9 +123,9 @@ public:
     struct Object {
         Object() :
                 type(World),
-                name(""),
+                name(),
                 children(),
-                texture(""),
+                texture(),
                 texRepeat(1.f, 1.f),
                 texOffset(0.0f, 0.0f),
                 rotation(),

+ 0 - 4
code/AssetLib/AMF/AMFImporter.cpp

@@ -517,10 +517,6 @@ bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool p
     return false;
 }
 
-void AMFImporter::GetExtensionList(std::set<std::string> &pExtensionList) {
-    pExtensionList.insert("amf");
-}
-
 const aiImporterDesc *AMFImporter::GetInfo() const {
     return &Description;
 }

+ 0 - 1
code/AssetLib/AMF/AMFImporter.hpp

@@ -277,7 +277,6 @@ public:
     void ParseHelper_Node_Enter(AMFNodeElementBase *child);
     void ParseHelper_Node_Exit();
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
-    void GetExtensionList(std::set<std::string> &pExtensionList);
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
     const aiImporterDesc *GetInfo() const;
     bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;

+ 2 - 2
code/AssetLib/AMF/AMFImporter_Postprocess.cpp

@@ -428,10 +428,10 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
 
                     if (pBiggerThan != nullptr) {
                         bool found = false;
-
+                        const size_t biggerThan = *pBiggerThan;
                         for (const SComplexFace &face : pFaceList) {
                             for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) {
-                                if (face.Face.mIndices[idx_vert] > *pBiggerThan) {
+                                if (face.Face.mIndices[idx_vert] > biggerThan) {
                                     rv = face.Face.mIndices[idx_vert];
                                     found = true;
                                     break;

+ 1 - 1
code/AssetLib/ASE/ASEParser.cpp

@@ -685,7 +685,7 @@ void Parser::ParseLV3MapBlock(Texture &map) {
                     // Files with 'None' as map name are produced by
                     // an Maja to ASE exporter which name I forgot ..
                     ASSIMP_LOG_WARN("ASE: Skipping invalid map entry");
-                    map.mMapName = "";
+                    map.mMapName = std::string();
                 }
 
                 continue;

+ 1 - 7
code/AssetLib/Blender/BlenderLoader.cpp

@@ -88,7 +88,7 @@ using namespace Assimp::Blender;
 using namespace Assimp::Formatter;
 
 static const aiImporterDesc blenderDesc = {
-    "Blender 3D Importer \nhttp://www.blender3d.org",
+    "Blender 3D Importer (http://www.blender3d.org)",
     "",
     "",
     "No animation support yet",
@@ -132,12 +132,6 @@ bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bo
     return false;
 }
 
-// ------------------------------------------------------------------------------------------------
-// List all extensions handled by this loader
-void BlenderImporter::GetExtensionList(std::set<std::string> &app) {
-    app.insert("blend");
-}
-
 // ------------------------------------------------------------------------------------------------
 // Loader registry entry
 const aiImporterDesc *BlenderImporter::GetInfo() const {

+ 0 - 1
code/AssetLib/Blender/BlenderLoader.h

@@ -110,7 +110,6 @@ public:
 
 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);

+ 2 - 2
code/AssetLib/Collada/ColladaLoader.cpp

@@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
     3,
     1,
     5,
-    "dae zae"
+    "dae xml zae"
 };
 
 static const float kMillisecondsFromSeconds = 1000.f;
@@ -1241,7 +1241,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
                     continue;
                 }
                 entry.mTargetId = entry.mTransformId;
-                entry.mTransformId = "";
+                entry.mTransformId = std::string();
             }
 
             entry.mChannel = &(*cit);

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

@@ -330,7 +330,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
         }
 
         const Element* Name = source["Name"];
-        m_uvNames[index] = "";
+        m_uvNames[index] = std::string();
         if(Name) {
             m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
         }

+ 4 - 4
code/AssetLib/FBX/FBXParser.cpp

@@ -462,7 +462,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
 
     if (t.Type() != TokenType_DATA) {
         err_out = "expected TOK_DATA token";
-        return "";
+        return std::string();
     }
 
     if(t.IsBinary())
@@ -470,7 +470,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
         const char* data = t.begin();
         if (data[0] != 'S') {
             err_out = "failed to parse S(tring), unexpected data type (binary)";
-            return "";
+            return std::string();
         }
 
         // read string length
@@ -484,13 +484,13 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
     const size_t length = static_cast<size_t>(t.end() - t.begin());
     if(length < 2) {
         err_out = "token is too short to hold a string";
-        return "";
+        return std::string();
     }
 
     const char* s = t.begin(), *e = t.end() - 1;
     if (*s != '\"' || *e != '\"') {
         err_out = "expected double quoted string";
-        return "";
+        return std::string();
     }
 
     return std::string(s+1,length-2);

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

@@ -155,7 +155,7 @@ std::string PeekPropertyName(const Element& element)
     ai_assert(element.KeyToken().StringContents() == "P");
     const TokenList& tok = element.Tokens();
     if(tok.size() < 4) {
-        return "";
+        return std::string();
     }
 
     return ParseTokenAsString(*tok[0]);

+ 2 - 2
code/AssetLib/IFC/IFCLoader.cpp

@@ -567,7 +567,7 @@ typedef std::map<std::string, std::string> Metadata;
 
 // ------------------------------------------------------------------------------------------------
 void ProcessMetadata(const Schema_2x3::ListOf<Schema_2x3::Lazy<Schema_2x3::IfcProperty>, 1, 0> &set, ConversionData &conv, Metadata &properties,
-        const std::string &prefix = "",
+        const std::string &prefix = std::string(),
         unsigned int nest = 0) {
     for (const Schema_2x3::IfcProperty &property : set) {
         const std::string &key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
@@ -618,7 +618,7 @@ void ProcessMetadata(const Schema_2x3::ListOf<Schema_2x3::Lazy<Schema_2x3::IfcPr
                 ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1);
             }
         } else {
-            properties[key] = "";
+            properties[key] = std::string();
         }
     }
 }

+ 1 - 1
code/AssetLib/Irr/IRRLoader.cpp

@@ -859,7 +859,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
 	// Check whether we can read from the file
 	if (file.get() == nullptr) {
-		throw DeadlyImportError("Failed to open IRR file " + pFile + "");
+		throw DeadlyImportError("Failed to open IRR file " + pFile);
 	}
 
 	// Construct the irrXML parser

+ 1 - 1
code/AssetLib/Irr/IRRMeshLoader.cpp

@@ -135,7 +135,7 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
 
 	// Check whether we can read from the file
 	if (file.get() == NULL)
-		throw DeadlyImportError("Failed to open IRRMESH file " + pFile + "");
+		throw DeadlyImportError("Failed to open IRRMESH file " + pFile);
 
 	// Construct the irrXML parser
 	XmlParser parser;

+ 1 - 1
code/AssetLib/LWO/LWOFileData.h

@@ -502,7 +502,7 @@ struct Surface {
     Surface() :
             mColor(0.78431f, 0.78431f, 0.78431f), bDoubleSided(false), mDiffuseValue(1.f), mSpecularValue(0.f), mTransparency(0.f), mGlossiness(0.4f), mLuminosity(0.f), mColorHighlights(0.f), mMaximumSmoothAngle(0.f) // 0 == not specified, no smoothing
             ,
-            mVCMap(""),
+            mVCMap(),
             mVCMapType(AI_LWO_RGBA),
             mIOR(1.f) // vakuum
             ,

+ 1 - 1
code/AssetLib/LWS/LWSLoader.h

@@ -88,7 +88,7 @@ struct NodeDesc {
             id(),
             number(0),
             parent(0),
-            name(""),
+            name(),
             isPivotSet(false),
             lightColor(1.f, 1.f, 1.f),
             lightIntensity(1.f),

+ 2 - 3
code/AssetLib/M3D/M3DImporter.cpp

@@ -95,10 +95,9 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-#ifdef M3D_ASCII
-    "m3d a3d"
-#else
     "m3d"
+#ifdef M3D_ASCII
+    " a3d"
 #endif
 };
 

+ 1 - 1
code/AssetLib/MD2/MD2NormalTable.h

@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_MDL_NORMALTABLE_H_INC
 
 
-float g_avNormals[162][3] = {
+const float g_avNormals[162][3] = {
 { -0.525731f,  0.000000f,  0.850651f },
 { -0.442863f,  0.238856f,  0.864188f },
 { -0.295242f,  0.000000f,  0.955423f },

+ 1 - 1
code/AssetLib/MDC/MDCNormalTable.h

@@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define MDC_NORMAL_TABLE_INCLUDED
 
 /* mdc decoding normal table */
-float mdcNormals[ 256 ][ 3 ] =
+const float mdcNormals[ 256 ][ 3 ] =
 {
     { 1.000000f, 0.000000f, 0.000000f },
     { 0.980785f, 0.195090f, 0.000000f },

+ 1 - 1
code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp

@@ -95,7 +95,7 @@ void UniqueNameGenerator::make_unique(std::vector<std::string> &names) {
     auto generate_unique_name = [&](const std::string &base_name) -> std::string {
         auto *duplicate_info = &names_to_duplicates[base_name];
 
-        std::string new_name = "";
+        std::string new_name;
 
         bool found_identical_name;
         bool tried_with_base_name_only = false;

+ 1 - 1
code/AssetLib/MMD/MMDImporter.cpp

@@ -75,7 +75,7 @@ using namespace std;
 //  Default constructor
 MMDImporter::MMDImporter() :
         m_Buffer(),
-        m_strAbsPath("") {
+        m_strAbsPath() {
     DefaultIOSystem io;
     m_strAbsPath = io.getOsSeparator();
 }

+ 1 - 1
code/AssetLib/MMD/MMDPmxParser.cpp

@@ -91,7 +91,7 @@ namespace pmx
 		std::vector<char> buffer;
 		if (size == 0)
 		{
-			return std::string("");
+			return std::string();
 		}
 		buffer.reserve(size);
 		stream->read((char*) buffer.data(), size);

+ 1 - 1
code/AssetLib/OpenGEX/OpenGEXImporter.cpp

@@ -206,7 +206,7 @@ USE_ODDLPARSER_NS
 
 //------------------------------------------------------------------------------------------------
 static void propId2StdString(Property *prop, std::string &name, std::string &key) {
-    name = key = "";
+    name = key = std::string();
     if (nullptr == prop) {
         return;
     }

+ 1 - 1
code/AssetLib/OpenGEX/OpenGEXImporter.h

@@ -79,7 +79,7 @@ struct MetricInfo {
     int m_intValue;
 
     MetricInfo()
-    : m_stringValue( "" )
+    : m_stringValue( )
     , m_floatValue( 0.0f )
     , m_intValue( -1 ) {
         // empty

+ 1 - 1
code/AssetLib/Q3BSP/Q3BSPFileData.h

@@ -178,7 +178,7 @@ struct Q3BSPModel {
         m_Textures(),
         m_Lightmaps(),
         m_EntityData(),
-        m_ModelName( "" )
+        m_ModelName()
     {
         // empty
     }

+ 9 - 9
code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp

@@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-    "pk3"
+    "bsp pk3"
 };
 
 namespace Assimp {
@@ -113,7 +113,7 @@ static void extractIds(const std::string &key, int &id1, int &id2) {
 // ------------------------------------------------------------------------------------------------
 //  Local helper function to normalize filenames.
 static void normalizePathName(const std::string &rPath, std::string &normalizedPath) {
-    normalizedPath = "";
+    normalizedPath = std::string();
     if (rPath.empty()) {
         return;
     }
@@ -183,7 +183,7 @@ void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene,
         throw DeadlyImportError("Failed to open file ", rFile, ".");
     }
 
-    std::string archiveName(""), mapName("");
+    std::string archiveName, mapName;
     separateMapName(rFile, archiveName, mapName);
 
     if (mapName.empty()) {
@@ -202,8 +202,8 @@ void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene,
 // ------------------------------------------------------------------------------------------------
 //  Separates the map name from the import name.
 void Q3BSPFileImporter::separateMapName(const std::string &importName, std::string &archiveName, std::string &mapName) {
-    archiveName = "";
-    mapName = "";
+    archiveName = std::string();
+    mapName = std::string();
     if (importName.empty()) {
         return;
     }
@@ -221,7 +221,7 @@ void Q3BSPFileImporter::separateMapName(const std::string &importName, std::stri
 // ------------------------------------------------------------------------------------------------
 //  Returns the first map in the map archive.
 bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, std::string &mapName) {
-    mapName = "";
+    mapName = std::string();
     std::vector<std::string> fileList;
     bspArchive.getFileListExtension(fileList, "bsp");
     if (fileList.empty()) {
@@ -440,7 +440,7 @@ void Q3BSPFileImporter::createMaterials(const Q3BSP::Q3BSPModel *pModel, aiScene
         if (-1 != textureId) {
             sQ3BSPTexture *pTexture = pModel->m_Textures[textureId];
             if (nullptr != pTexture) {
-                std::string tmp("*"), texName("");
+                std::string tmp("*"), texName;
                 tmp += pTexture->strName;
                 tmp += ".jpg";
                 normalizePathName(tmp, texName);
@@ -512,7 +512,7 @@ size_t Q3BSPFileImporter::countTriangles(const std::vector<Q3BSP::sQ3BSPFace *>
 // ------------------------------------------------------------------------------------------------
 //  Creates the faces-to-material map.
 void Q3BSPFileImporter::createMaterialMap(const Q3BSP::Q3BSPModel *pModel) {
-    std::string key("");
+    std::string key;
     std::vector<sQ3BSPFace *> *pCurFaceArray = nullptr;
     for (size_t idx = 0; idx < pModel->m_Faces.size(); idx++) {
         Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[idx];
@@ -660,7 +660,7 @@ bool Q3BSPFileImporter::expandFile(ZipArchiveIOSystem *pArchive, const std::stri
 
     if (rExtList.empty()) {
         rFile = rFilename;
-        rExt = "";
+        rExt = std::string();
         return true;
     }
 

+ 1 - 1
code/AssetLib/X/XFileHelper.h

@@ -130,7 +130,7 @@ struct Mesh {
 
     std::vector<Bone> mBones;
 
-    explicit Mesh(const std::string &pName = "") AI_NO_EXCEPT
+    explicit Mesh(const std::string &pName = std::string()) AI_NO_EXCEPT
     : mName( pName )
     , mPositions()
     , mPosFaces()

+ 0 - 4
code/AssetLib/X3D/X3DImporter.cpp

@@ -167,10 +167,6 @@ bool X3DImporter::CanRead( const std::string &pFile, IOSystem * /*pIOHandler*/,
     return false;
 }
 
-void X3DImporter::GetExtensionList( std::set<std::string> &extensionList ) {
-    extensionList.insert("x3d");
-}
-
 void X3DImporter::InternReadFile( const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler ) {
     std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
     if (!stream) {

+ 0 - 1
code/AssetLib/X3D/X3DImporter.hpp

@@ -307,7 +307,6 @@ public:
     /// \param [in] pIOHandler - pointer to IO helper object.
     void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
-    void GetExtensionList(std::set<std::string> &pExtensionList);
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
     const aiImporterDesc *GetInfo() const;
     void Clear();

+ 1 - 1
code/AssetLib/XGL/XGLLoader.cpp

@@ -142,7 +142,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
 	// check whether we can read from the file
 	if (stream.get() == NULL) {
-		throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + "");
+		throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile);
 	}
 
 	// see if its compressed, if so uncompress it

+ 1 - 1
code/AssetLib/glTF/glTFAsset.h

@@ -1033,7 +1033,7 @@ namespace glTF
 
         AssetMetadata()
             : premultipliedAlpha(false)
-            , version("")
+            , version()
         {
         }
     };

+ 1 - 1
code/AssetLib/glTF2/glTF2Asset.h

@@ -1071,7 +1071,7 @@ struct AssetMetadata {
     void Read(Document &doc);
 
     AssetMetadata() :
-            version("") {}
+            version() {}
 };
 
 //

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

@@ -162,6 +162,9 @@ inline static bool ReadValue(Value &val, T &out) {
 
 template <class T>
 inline static bool ReadMember(Value &obj, const char *id, T &out) {
+    if (!obj.IsObject()) {
+        return false;
+    }
     Value::MemberIterator it = obj.FindMember(id);
     if (it != obj.MemberEnd()) {
         return ReadHelper<T>::Read(it->value, out);
@@ -176,6 +179,9 @@ inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
 }
 
 inline Value *FindMember(Value &val, const char *id) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(id);
     return (it != val.MemberEnd()) ? &it->value : nullptr;
 }
@@ -193,6 +199,9 @@ inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const ch
 // Look-up functions with type checks. Context and extra context help the user identify the problem if there's an error.
 
 inline Value *FindStringInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -204,6 +213,9 @@ inline Value *FindStringInContext(Value &val, const char *memberId, const char*
 }
 
 inline Value *FindNumberInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -215,6 +227,9 @@ inline Value *FindNumberInContext(Value &val, const char *memberId, const char*
 }
 
 inline Value *FindUIntInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -226,6 +241,9 @@ inline Value *FindUIntInContext(Value &val, const char *memberId, const char* co
 }
 
 inline Value *FindArrayInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -237,6 +255,9 @@ inline Value *FindArrayInContext(Value &val, const char *memberId, const char* c
 }
 
 inline Value *FindObjectInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -886,7 +907,7 @@ inline void Accessor::Read(Value &obj, Asset &r) {
     componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
     {
         const Value* countValue = FindUInt(obj, "count");
-        if (!countValue || countValue->GetInt() < 1)
+        if (!countValue || countValue->GetUint() < 1)
         {
             throw DeadlyImportError("A strictly positive count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
         }
@@ -1105,7 +1126,9 @@ inline Accessor::Indexer::Indexer(Accessor &acc) :
 template <class T>
 T Accessor::Indexer::GetValue(int i) {
     ai_assert(data);
-    ai_assert(i * stride < accessor.GetMaxByteSize());
+    if (i * stride >= accessor.GetMaxByteSize()) {
+        throw DeadlyImportError("GLTF: Invalid index ", i, ", count out of range for buffer with stride ", stride, " and size ", accessor.GetMaxByteSize(), ".");
+    }
     // Ensure that the memcpy doesn't overwrite the local.
     const size_t sizeToCopy = std::min(elemSize, sizeof(T));
     T value = T();

+ 3 - 3
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -1172,7 +1172,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
 
         static const float kMillisecondsFromSeconds = 1000.f;
 
-        if (samplers.translation) {
+        if (samplers.translation && samplers.translation->input && samplers.translation->output) {
             float *times = nullptr;
             samplers.translation->input->ExtractData(times);
             aiVector3D *values = nullptr;
@@ -1196,7 +1196,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
             anim->mPositionKeys->mValue.z = node.translation.value[2];
         }
 
-        if (samplers.rotation) {
+        if (samplers.rotation && samplers.rotation->input && samplers.rotation->output) {
             float *times = nullptr;
             samplers.rotation->input->ExtractData(times);
             aiQuaternion *values = nullptr;
@@ -1224,7 +1224,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
             anim->mRotationKeys->mValue.w = node.rotation.value[3];
         }
 
-        if (samplers.scale) {
+        if (samplers.scale && samplers.scale->input && samplers.scale->output) {
             float *times = nullptr;
             samplers.scale->input->ExtractData(times);
             aiVector3D *values = nullptr;

+ 2 - 2
code/CApi/CInterfaceIOWrapper.cpp

@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
-CIOStreamWrapper::~CIOStreamWrapper(void) {
+CIOStreamWrapper::~CIOStreamWrapper() {
     /* Various places depend on this destructor to close the file */
     if (mFile) {
         mIO->mFileSystem->CloseProc(mIO->mFileSystem, mFile);
@@ -78,7 +78,7 @@ aiReturn CIOStreamWrapper::Seek(size_t pOffset,
 }
 
 // ...................................................................
-size_t CIOStreamWrapper::Tell(void) const {
+size_t CIOStreamWrapper::Tell() const {
     return mFile->TellProc(mFile);
 }
 

+ 2 - 2
code/Common/BaseImporter.cpp

@@ -83,7 +83,7 @@ void BaseImporter::UpdateImporterScale(Importer *pImp) {
     // Set active scaling
     pImp->SetPropertyFloat(AI_CONFIG_APP_SCALE_KEY, static_cast<float>(activeScale));
 
-    ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale);
+    ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: ", activeScale);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -257,7 +257,7 @@ std::string BaseImporter::GetExtension(const std::string &file) {
 
     // no file extension at all
     if (pos == std::string::npos) {
-        return "";
+        return std::string();
     }
 
     // thanks to Andy Maloney for the hint

+ 4 - 2
code/Common/DefaultIOStream.cpp

@@ -90,10 +90,12 @@ DefaultIOStream::~DefaultIOStream() {
 size_t DefaultIOStream::Read(void *pvBuffer,
         size_t pSize,
         size_t pCount) {
+    if (0 == pCount) {
+        return 0;
+    }
     ai_assert(nullptr != pvBuffer);
     ai_assert(0 != pSize);
-    ai_assert(0 != pCount);
-
+    
     return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
 }
 

+ 1 - 1
code/Common/FileSystemFilter.h

@@ -76,7 +76,7 @@ public:
         if (std::string::npos != (ss2 = mBase.find_last_of("\\/")))  {
             mBase.erase(ss2,mBase.length()-ss2);
         } else {
-            mBase = "";
+            mBase = std::string();
         }
 
         // make sure the directory is terminated properly

+ 3 - 3
code/Common/Importer.cpp

@@ -149,7 +149,7 @@ void AllocateFromAssimpHeap::operator delete[] ( void* data)    {
 Importer::Importer()
  : pimpl( new ImporterPimpl ) {
     pimpl->mScene = nullptr;
-    pimpl->mErrorString = "";
+    pimpl->mErrorString = std::string();
 
     // Allocate a default IO handler
     pimpl->mIOHandler = new DefaultIOSystem;
@@ -387,7 +387,7 @@ void Importer::FreeScene( ) {
     delete pimpl->mScene;
     pimpl->mScene = nullptr;
 
-    pimpl->mErrorString = "";
+    pimpl->mErrorString = std::string();
     pimpl->mException = std::exception_ptr();
     ASSIMP_END_EXCEPTION_REGION(void);
 }
@@ -434,7 +434,7 @@ aiScene* Importer::GetOrphanedScene() {
     ASSIMP_BEGIN_EXCEPTION_REGION();
     pimpl->mScene = nullptr;
 
-    pimpl->mErrorString = ""; // reset error string
+    pimpl->mErrorString = std::string();
     pimpl->mException = std::exception_ptr();
     ASSIMP_END_EXCEPTION_REGION(aiScene*);
     

+ 4 - 2
code/Common/SceneCombiner.cpp

@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // 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
@@ -359,7 +359,7 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
 
     // generate the output texture list + an offset table for all texture indices
     if (dest->mNumTextures) {
-        aiTexture **pip = dest->mTextures = new aiTexture *[dest->mNumMaterials];
+        aiTexture **pip = dest->mTextures = new aiTexture *[dest->mNumTextures];
         cnt = 0;
         for (unsigned int n = 0; n < src.size(); ++n) {
             SceneHelper *cur = &src[n];
@@ -638,6 +638,8 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
         deleteMe->mMaterials = nullptr;
         delete[] deleteMe->mAnimations;
         deleteMe->mAnimations = nullptr;
+        delete[] deleteMe->mTextures;
+        deleteMe->mTextures = nullptr;
 
         deleteMe->mRootNode = nullptr;
 

+ 1 - 1
code/Common/scene.cpp

@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 
 aiNode::aiNode()
-: mName("")
+: mName()
 , mParent(nullptr)
 , mNumChildren(0)
 , mChildren(nullptr)

+ 1 - 1
code/PostProcessing/RemoveRedundantMaterials.h

@@ -81,7 +81,7 @@ public:
     /** @brief Set list of fixed (inmutable) materials
      *  @param fixed See #AI_CONFIG_PP_RRM_EXCLUDE_LIST
      */
-    void SetFixedMaterialsString(const std::string& fixed = "") {
+    void SetFixedMaterialsString(const std::string& fixed = std::string()) {
         mConfigFixedMaterials = fixed;
     }
 

+ 3 - 1
code/PostProcessing/SortByPTypeProcess.cpp

@@ -135,7 +135,9 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
     std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
     for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
         aiMesh *const mesh = pScene->mMeshes[i];
-        ai_assert(0 != mesh->mPrimitiveTypes);
+        if (mesh->mPrimitiveTypes == 0) {
+            throw DeadlyImportError("Mesh with invalid primitive type: ", mesh->mName.C_Str());
+        }
 
         // if there's just one primitive type in the mesh there's nothing to do for us
         unsigned int num = 0;

+ 0 - 58
contrib/zip/.gitignore

@@ -1,58 +0,0 @@
-/build/
-/test/build/
-/xcodeproj/
-.vscode/
-
-# Object files
-*.o
-*.ko
-*.obj
-*.elf
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Libraries
-*.lib
-*.a
-*.la
-*.lo
-
-# Shared objects (inc. Windows DLLs)
-*.dll
-*.so
-*.so.*
-*.dylib
-*.suo
-
-# Executables
-*.exe
-*.out
-*.app
-*.i*86
-*.x86_64
-*.hex
-
-# Temporary
-*.swp
-.DS_Store
-
-# CMake
-CMakeScripts
-*.cmake
-
-# Xcode
-*.build
-*.xcodeproj
-zip.sln
-zip.vcxproj.filters
-zip.vcxproj
-ALL_BUILD.vcxproj.filters
-ALL_BUILD.vcxproj
-CMakeFiles/
-zip.dir/
-test/test.exe.vcxproj.filters
-test/test.exe.vcxproj
-test/test.exe.dir/
-

+ 29 - 15
contrib/zip/CMakeLists.txt

@@ -1,26 +1,29 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.4)
 
 project(zip
   LANGUAGES C
-  VERSION "0.1.18")
+  VERSION "0.1.19")
 set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
-
+set(CMAKE_VERBOSE_MAKEFILE ON)
 option(CMAKE_DISABLE_TESTING "Disable test creation" OFF)
 
-if (MSVC)
-  # Use secure functions by default and suppress warnings about "deprecated" functions
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
-elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
-        "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
-        "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic")
-endif (MSVC)
-
 # zip
 set(SRC src/miniz.h src/zip.h src/zip.c)
-add_library(${PROJECT_NAME} ${SRC})
+
+# this is the "object library" target: compiles the sources only once
+add_library(OBJLIB OBJECT ${SRC})
+# shared libraries need PIC
+set_property(TARGET OBJLIB PROPERTY POSITION_INDEPENDENT_CODE 1)
+
+# static and shared libraries built from the same object files
+if (BUILD_SHARED_LIBS)
+  add_library(${PROJECT_NAME} SHARED $<TARGET_OBJECTS:OBJLIB>)
+  include(GenerateExportHeader)
+  generate_export_header(${PROJECT_NAME})
+else()
+  add_library(${PROJECT_NAME} STATIC $<TARGET_OBJECTS:OBJLIB>)
+endif()
+
 target_include_directories(${PROJECT_NAME} PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
   $<INSTALL_INTERFACE:include>
@@ -34,6 +37,17 @@ if (NOT CMAKE_DISABLE_TESTING)
   add_sanitizers(${PROJECT_NAME} ${test_out})
 endif()
 
+if (MSVC)
+  # Use secure functions by default and suppress warnings about "deprecated" functions
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
+elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
+        "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
+        "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Werror -pedantic -Wno-deprecated")
+endif (MSVC)
+
 ####
 # Installation (https://github.com/forexample/package-example) {
 

+ 132 - 17
contrib/zip/README.md

@@ -2,7 +2,6 @@
 This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API.
 
 [![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild)
-[![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases)
 
 
 # The Idea
@@ -155,10 +154,52 @@ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
 zip_close(zip);
 ```
 
+* Create a new zip archive in memory (stream API).
+
+```c
+char *outbuf = NULL;
+size_t outbufsize = 0;
+
+const char *inbuf = "Append some data here...\0";
+struct zip_t *zip = zip_stream_open(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
+{
+    zip_entry_open(zip, "foo-1.txt");
+    {
+        zip_entry_write(zip, inbuf, strlen(inbuf));
+    }
+    zip_entry_close(zip);
+
+    /* copy compressed stream into outbuf */
+    zip_stream_copy(zip, (void **)&outbuf, &outbufsize);
+}
+zip_stream_close(zip);
+
+free(outbuf);
+```
+
+* Extract a zip entry into a memory (stream API).
+
+```c
+char *buf = NULL;
+ssize_t bufsize = 0;
+
+struct zip_t *zip = zip_stream_open(zipstream, zipstreamsize, 0, 'r');
+{
+    zip_entry_open(zip, "foo-1.txt");
+    {
+        zip_entry_read(zip, (void **)&buf, &bufsize);
+    }
+    zip_entry_close(zip);
+}
+zip_stream_close(zip);
+
+free(buf);
+```
+
 * List of all zip entries
 ```c
 struct zip_t *zip = zip_open("foo.zip", 0, 'r');
-int i, n = zip_total_entries(zip);
+int i, n = zip_entries_total(zip);
 for (i = 0; i < n; ++i) {
     zip_entry_openbyindex(zip, i);
     {
@@ -172,6 +213,49 @@ for (i = 0; i < n; ++i) {
 zip_close(zip);
 ```
 
+* Compress folder (recursively)
+```c
+void zip_walk(struct zip_t *zip, const char *path) {
+    DIR *dir;
+    struct dirent *entry;
+    char fullpath[MAX_PATH];
+    struct stat s;
+
+    memset(fullpath, 0, MAX_PATH);
+    dir = opendir(path);
+    assert(dir);
+
+    while ((entry = readdir(dir))) {
+      // skip "." and ".."
+      if (!strcmp(entry->d_name, ".\0") || !strcmp(entry->d_name, "..\0"))
+        continue;
+
+      snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entry->d_name);
+      stat(fullpath, &s);
+      if (S_ISDIR(s.st_mode))
+        zip_walk(zip, fullpath);
+      else {
+        zip_entry_open(zip, fullpath);
+        zip_entry_fwrite(zip, fullpath);
+        zip_entry_close(zip);
+      }
+    }
+
+    closedir(dir);
+}
+```
+
+* Deletes zip archive entries.
+```c
+char *entries[] = {"unused.txt", "remove.ini", "delete.me"};
+
+struct zip_t *zip = zip_open("foo.zip", 0, 'd');
+{
+    zip_entries_delete(zip, entries, 3);
+}
+zip_close(zip);
+```
+
 # Bindings
 Compile zip library as a dynamic library.
 ```shell
@@ -181,7 +265,7 @@ $ cmake -DBUILD_SHARED_LIBS=true ..
 $ make
 ```
 
-### Go (cgo)
+### [Go](https://golang.org) (cgo)
 ```go
 package main
 
@@ -211,7 +295,7 @@ func main() {
 }
 ```
 
-### Rust (ffi)
+### [Rust](https://www.rust-lang.org) (ffi)
 ```rust
 extern crate libc;
 use std::ffi::CString;
@@ -236,7 +320,7 @@ extern "C" {
 }
 
 fn main() {
-    let path = CString::new("/tmp/test.zip").unwrap();
+    let path = CString::new("/tmp/rust.zip").unwrap();
     let mode: libc::c_char = 'w' as libc::c_char;
 
     let entryname = CString::new("test.txt").unwrap();
@@ -258,7 +342,7 @@ fn main() {
 }
 ```
 
-### Ruby (ffi)
+### [Ruby](http://www.ruby-lang.org) (ffi)
 Install _ffi_ gem.
 ```shell
 $ gem install ffi
@@ -291,7 +375,7 @@ Zip.zip_entry_close(ptr)
 Zip.zip_close(ptr)
 ```
 
-### Python (cffi)
+### [Python](https://www.python.org) (cffi)
 Install _cffi_ package
 ```shell
 $ pip install cffi
@@ -325,7 +409,36 @@ Zip.zip_entry_close(ptr)
 Zip.zip_close(ptr)
 ```
 
-### Ring
+### [Never](https://never-lang.readthedocs.io/) (ffi)
+```never
+extern "libzip.so" func zip_open(zipname: string, level: int, mode: char) -> c_ptr
+extern "libzip.so" func zip_close(zip: c_ptr) -> void
+
+extern "libzip.so" func zip_entry_open(zip: c_ptr, entryname: string) -> int
+extern "libzip.so" func zip_entry_close(zip: c_ptr) -> int
+extern "libzip.so" func zip_entry_write(zip: c_ptr, buf: string, bufsize: int) -> int
+extern "libzip.so" func zip_entry_fwrite(zip: c_ptr, filename: string) -> int
+
+func main() -> int
+{
+    let content = "Test content"
+
+    let zip = zip_open("/tmp/never.zip", 6, 'w');
+
+    zip_entry_open(zip, "test.file");
+    zip_entry_fwrite(zip, "/tmp/test.txt");
+    zip_entry_close(zip);
+
+    zip_entry_open(zip, "test.content");
+    zip_entry_write(zip, content, length(content));
+    zip_entry_close(zip);
+
+    zip_close(zip);
+    0
+}
+```
+
+### [Ring](http://ring-lang.net)
 The language comes with RingZip based on this library
 ```ring
 load "ziplib.ring"
@@ -342,13 +455,15 @@ new Zip {
 }
 ```
 
-# Contribution Rules/Coding Standards
-No need to throw away your coding style, just do your best to follow default clang-format style.
-Apply `clang-format` to the source files before commit:
-```sh
-for file in $(git ls-files | \grep -E '\.(c|h)$' | \grep -v -- '#')
-do
-    clang-format -i $file
-done
-```
+# Check out more cool projects which use this library:
+- [Filament](https://github.com/google/filament): Filament is a real-time physically based rendering engine for Android, iOS, Linux, macOS, Windows, and WebGL. It is designed to be as small as possible and as efficient as possible on Android.
+- [Hermes JS Engine](https://github.com/facebook/hermes): Hermes is a JavaScript engine optimized for fast start-up of React Native apps on Android. It features ahead-of-time static optimization and compact bytecode.
+- [Open Asset Import Library](https://github.com/assimp/assimp): A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
+- [PowerToys](https://github.com/microsoft/PowerToys): Set of utilities for power users to tune and streamline their Windows 10 experience for greater productivity.
+- [The Ring Programming Language](https://ring-lang.github.io): Innovative and practical general-purpose multi-paradigm language.
+- [The V Programming Language](https://github.com/vlang/v): Simple, fast, safe, compiled. For developing maintainable software.
+- [TIC-80](https://github.com/nesbox/TIC-80): TIC-80 is a FREE and OPEN SOURCE fantasy computer for making, playing and sharing tiny games.
+- [Urho3D](https://github.com/urho3d/Urho3D): Urho3D is a free lightweight, cross-platform 2D and 3D game engine implemented in C++ and released under the MIT license. Greatly inspired by OGRE and Horde3D.
+- [Vcpkg](https://github.com/microsoft/vcpkg): Vcpkg helps you manage C and C++ libraries on Windows, Linux and MacOS.
+- [and more...](https://grep.app/search?q=kuba--/zip)
 

+ 45 - 29
contrib/zip/src/miniz.h

@@ -400,7 +400,7 @@ typedef enum {
 #ifndef MINIZ_NO_ZLIB_APIS
 
 // Heap allocation callbacks.
-// Note that mz_alloc_func parameter types purpsosely differ from zlib's:
+// Note that mz_alloc_func parameter types purposely differ from zlib's:
 // items/size is size_t, not unsigned long.
 typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
 typedef void (*mz_free_func)(void *opaque, void *address);
@@ -2194,7 +2194,8 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r,
             } else
               tree_cur = pTable->m_tree[-tree_cur - 1];
           }
-          tree_cur -= ((rev_code >>= 1) & 1);
+          rev_code >>= 1;
+          tree_cur -= (rev_code & 1);
           pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
         }
         if (r->m_type == 2) {
@@ -3970,6 +3971,7 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
 
 #ifdef _MSC_VER
 #pragma warning(push)
+#pragma warning(disable : 4121 4127 4244)
 #pragma warning(disable : 4204) // nonstandard extension used : non-constant
                                 // aggregate initializer (also supported by GNU
                                 // C and C99, so no big deal)
@@ -4098,10 +4100,6 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
                                                     pLen_out, 6, MZ_FALSE);
 }
 
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
 // ------------------- .ZIP archive reading
 
 #ifndef MINIZ_NO_ARCHIVE_APIS
@@ -4112,18 +4110,39 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
 #include <stdio.h>
 #include <sys/stat.h>
 
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+
+#include <windows.h>
+
+static wchar_t *str2wstr(const char *str) {
+  int len = (int) strlen(str) + 1;
+  wchar_t *wstr = malloc(len * sizeof(wchar_t));
+  MultiByteToWideChar(CP_UTF8, 0, str, len * sizeof(char), wstr, len);
+  return wstr;
+}
+
 static FILE *mz_fopen(const char *pFilename, const char *pMode) {
-  FILE *pFile = NULL;
-  fopen_s(&pFile, pFilename, pMode);
+  wchar_t *wFilename = str2wstr(pFilename);
+  wchar_t *wMode = str2wstr(pMode);
+  FILE *pFile = _wfopen(wFilename, wMode);
+
+  free(wFilename);
+  free(wMode);
+
   return pFile;
 }
+
 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
-  FILE *pFile = NULL;
-  if (freopen_s(&pFile, pPath, pMode, pStream))
-    return NULL;
+  wchar_t *wPath = str2wstr(pPath);
+  wchar_t *wMode = str2wstr(pMode);
+  FILE *pFile = _wfreopen(wPath, wMode, pStream);
+
+  free(wPath);
+  free(wMode);
+
   return pFile;
 }
+
 #ifndef MINIZ_NO_TIME
 #include <sys/utime.h>
 #endif
@@ -4144,7 +4163,7 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
 #include <sys/utime.h>
 #endif
 #define MZ_FILE FILE
-#define MZ_FOPEN(f, m) fopen(f, m)
+#define MZ_FOPEN(f, m) mz_fopen
 #define MZ_FCLOSE fclose
 #define MZ_FREAD fread
 #define MZ_FWRITE fwrite
@@ -4153,7 +4172,7 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
 #define MZ_FILE_STAT_STRUCT _stat
 #define MZ_FILE_STAT _stat
 #define MZ_FFLUSH fflush
-#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+#define MZ_FREOPEN(f, m, s) mz_freopen
 #define MZ_DELETE_FILE remove
 #elif defined(__TINYC__)
 #ifndef MINIZ_NO_TIME
@@ -5361,13 +5380,9 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
   } else {
     // Temporarily allocate a read buffer.
     read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
-#if defined(_MSC_VER) && !defined(__clang__)
-    if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
-        (read_buf_size > 0x7FFFFFFF))
-#else
     if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
-#endif
       return MZ_FALSE;
+
     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
                                             (size_t)read_buf_size)))
       return MZ_FALSE;
@@ -5454,11 +5469,7 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
   uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
 
   alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
-#if defined(_MSC_VER) && !defined(__clang__)
-  if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
-#else
   if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
-#endif
     return NULL;
   if (NULL ==
       (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
@@ -5560,14 +5571,10 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
     // The file is stored or the caller has requested the compressed data.
     if (pZip->m_pState->m_pMem) {
-#if defined (_MSC_VER) && !defined(__clang__)
-      if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
-          (file_stat.m_comp_size > 0xFFFFFFFF))
-#else
       if (((sizeof(size_t) == sizeof(mz_uint32))) &&
           (file_stat.m_comp_size > 0xFFFFFFFF))
-#endif
         return MZ_FALSE;
+
       if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
                     (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
         status = TINFL_STATUS_FAILED;
@@ -6085,7 +6092,7 @@ mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) {
   if (!pZip->m_file_offset_alignment)
     return 0;
   n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
-  return (mz_uint)(pZip->m_file_offset_alignment - n) &
+  return (pZip->m_file_offset_alignment - n) &
          (pZip->m_file_offset_alignment - 1);
 }
 
@@ -6289,7 +6296,10 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
                                mz_uint32 ext_attributes) {
   mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
   mz_uint16 method = 0, dos_time = 0, dos_date = 0;
+#ifndef MINIZ_NO_TIME
   time_t file_modified_time;
+#endif
+
   mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
                                                         comp_size = 0;
   size_t archive_name_size;
@@ -6326,10 +6336,12 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
         comment_size + archive_name_size) > 0xFFFFFFFF))
     return MZ_FALSE;
 
+#ifndef MINIZ_NO_TIME
   memset(&file_modified_time, 0, sizeof(file_modified_time));
   if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
     return MZ_FALSE;
   mz_zip_time_t_to_dos_time(file_modified_time, &dos_time, &dos_date);
+#endif
 
   pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
   if (!pSrc_file)
@@ -6814,6 +6826,10 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
   return p;
 }
 
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
 #endif // #ifndef MINIZ_NO_STDIO
 
 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS

File diff suppressed because it is too large
+ 704 - 63
contrib/zip/src/zip.c


+ 109 - 27
contrib/zip/src/zip.h

@@ -15,19 +15,11 @@
 #include <string.h>
 #include <sys/types.h>
 
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4127 )
-#endif //_MSC_VER
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) &&               \
-    !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) &&              \
-    !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(_SSIZE_T_DECLARED)
-
+#if !defined(_POSIX_C_SOURCE) && defined(_MSC_VER)
 // 64-bit Windows is the only mainstream platform
 // where sizeof(long) != sizeof(void*)
 #ifdef _WIN64
@@ -35,15 +27,6 @@ typedef long long ssize_t; /* byte count or error */
 #else
 typedef long ssize_t; /* byte count or error */
 #endif
-
-#define _SSIZE_T_DEFINED
-#define _SSIZE_T_DEFINED_
-#define __DEFINED_ssize_t
-#define __ssize_t_defined
-#define _SSIZE_T
-#define _SSIZE_T_
-#define _SSIZE_T_DECLARED
-
 #endif
 
 #ifndef MAX_PATH
@@ -64,9 +47,49 @@ typedef long ssize_t; /* byte count or error */
 /**
  * Default zip compression level.
  */
-
 #define ZIP_DEFAULT_COMPRESSION_LEVEL 6
 
+/**
+ * Error codes
+ */
+#define ZIP_ENOINIT -1      // not initialized
+#define ZIP_EINVENTNAME -2  // invalid entry name
+#define ZIP_ENOENT -3       // entry not found
+#define ZIP_EINVMODE -4     // invalid zip mode
+#define ZIP_EINVLVL -5      // invalid compression level
+#define ZIP_ENOSUP64 -6     // no zip 64 support
+#define ZIP_EMEMSET -7      // memset error
+#define ZIP_EWRTENT -8      // cannot write data to entry
+#define ZIP_ETDEFLINIT -9   // cannot initialize tdefl compressor
+#define ZIP_EINVIDX -10     // invalid index
+#define ZIP_ENOHDR -11      // header not found
+#define ZIP_ETDEFLBUF -12   // cannot flush tdefl buffer
+#define ZIP_ECRTHDR -13     // cannot create entry header
+#define ZIP_EWRTHDR -14     // cannot write entry header
+#define ZIP_EWRTDIR -15     // cannot write to central dir
+#define ZIP_EOPNFILE -16    // cannot open file
+#define ZIP_EINVENTTYPE -17 // invalid entry type
+#define ZIP_EMEMNOALLOC -18 // extracting data using no memory allocation
+#define ZIP_ENOFILE -19     // file not found
+#define ZIP_ENOPERM -20     // no permission
+#define ZIP_EOOMEM -21      // out of memory
+#define ZIP_EINVZIPNAME -22 // invalid zip archive name
+#define ZIP_EMKDIR -23      // make dir error
+#define ZIP_ESYMLINK -24    // symlink error
+#define ZIP_ECLSZIP -25     // close archive error
+#define ZIP_ECAPSIZE -26    // capacity size too small
+#define ZIP_EFSEEK -27      // fseek error
+#define ZIP_EFREAD -28      // fread error
+#define ZIP_EFWRITE -29     // fwrite error
+
+/**
+ * Looks up the error message string coresponding to an error number.
+ * @param errnum error number
+ * @return error message string coresponding to errnum or NULL if error is not
+ * found.
+ */
+extern const char *zip_strerror(int errnum);
+
 /**
  * @struct zip_t
  *
@@ -242,8 +265,8 @@ extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize);
  *
  * @note ensure supplied output buffer is large enough.
  *       zip_entry_size function (returns uncompressed size for the current
- *       entry) can be handy to estimate how big buffer is needed. for large
- * entries, please take a look at zip_entry_extract function.
+ *       entry) can be handy to estimate how big buffer is needed.
+ *       For large entries, please take a look at zip_entry_extract function.
  *
  * @return the return code - the number of bytes actually read on success.
  *         Otherwise a -1 on error (e.g. bufsize is not large enough).
@@ -285,7 +308,71 @@ zip_entry_extract(struct zip_t *zip,
  * @return the return code - the number of entries on success, negative number
  *         (< 0) on error.
  */
-extern int zip_total_entries(struct zip_t *zip);
+extern int zip_entries_total(struct zip_t *zip);
+
+/**
+ * Deletes zip archive entries.
+ *
+ * @param zip zip archive handler.
+ * @param entries array of zip archive entries to be deleted.
+ * @param len the number of entries to be deleted.
+ * @return the number of deleted entries, or negative number (< 0) on error.
+ */
+extern int zip_entries_delete(struct zip_t *zip, char *const entries[],
+                              size_t len);
+
+/**
+ * Extracts a zip archive stream into directory.
+ *
+ * If on_extract is not NULL, the callback will be called after
+ * successfully extracted each zip entry.
+ * Returning a negative value from the callback will cause abort and return an
+ * error. The last argument (void *arg) is optional, which you can use to pass
+ * data to the on_extract callback.
+ *
+ * @param stream zip archive stream.
+ * @param size stream size.
+ * @param dir output directory.
+ * @param on_extract on extract callback.
+ * @param arg opaque pointer.
+ *
+ * @return the return code - 0 on success, negative number (< 0) on error.
+ */
+extern int zip_stream_extract(const char *stream, size_t size, const char *dir,
+                              int (*on_extract)(const char *filename,
+                                                void *arg),
+                              void *arg);
+
+/**
+ * Opens zip archive stream into memory.
+ *
+ * @param stream zip archive stream.
+ * @param size stream size.
+ *
+ * @return the zip archive handler or NULL on error
+ */
+extern struct zip_t *zip_stream_open(const char *stream, size_t size, int level,
+                                     char mode);
+
+/**
+ * Copy zip archive stream output buffer.
+ *
+ * @param zip zip archive handler.
+ * @param buf output buffer. User should free buf.
+ * @param bufsize output buffer size (in bytes).
+ *
+ * @return copy size
+ */
+extern ssize_t zip_stream_copy(struct zip_t *zip, void **buf, ssize_t *bufsize);
+
+/**
+ * Close zip archive releases resources.
+ *
+ * @param zip zip archive handler.
+ *
+ * @return
+ */
+extern void zip_stream_close(struct zip_t *zip);
 
 /**
  * Creates a new archive and puts files into a single zip archive.
@@ -319,11 +406,6 @@ extern int zip_extract(const char *zipname, const char *dir,
                        void *arg);
 
 /** @} */
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif //_MSC_VER
-
 #ifdef __cplusplus
 }
 #endif

+ 34 - 7
contrib/zip/test/CMakeLists.txt

@@ -1,11 +1,38 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.4)
 
-# test
-set(test_out test.out)
+# tests
+set(test_write_out test_write.out)
+add_executable(${test_write_out} test_write.c)
+target_link_libraries(${test_write_out} zip)
+add_test(NAME ${test_write_out} COMMAND ${test_write_out})
+set(test_write_out ${test_write_out} PARENT_SCOPE)
 
-add_executable(${test_out} test.c)
-target_link_libraries(${test_out} zip)
+set(test_append_out test_append.out)
+add_executable(${test_append_out} test_append.c)
+target_link_libraries(${test_append_out} zip)
+add_test(NAME ${test_append_out} COMMAND ${test_append_out})
+set(test_append_out ${test_append_out} PARENT_SCOPE)
 
-add_test(NAME ${test_out} COMMAND ${test_out})
+set(test_read_out test_read.out)
+add_executable(${test_read_out} test_read.c)
+target_link_libraries(${test_read_out} zip)
+add_test(NAME ${test_read_out} COMMAND ${test_read_out})
+set(test_read_out ${test_read_out} PARENT_SCOPE)
 
-set(test_out ${test_out} PARENT_SCOPE)
+set(test_extract_out test_extract.out)
+add_executable(${test_extract_out} test_extract.c)
+target_link_libraries(${test_extract_out} zip)
+add_test(NAME ${test_extract_out} COMMAND ${test_extract_out})
+set(test_extract_out ${test_extract_out} PARENT_SCOPE)
+
+set(test_entry_out test_entry.out)
+add_executable(${test_entry_out} test_entry.c)
+target_link_libraries(${test_entry_out} zip)
+add_test(NAME ${test_entry_out} COMMAND ${test_entry_out})
+set(test_entry_out ${test_entry_out} PARENT_SCOPE)
+
+set(test_permissions_out test_permissions.out)
+add_executable(${test_permissions_out} test_permissions.c)
+target_link_libraries(${test_permissions_out} zip)
+add_test(NAME ${test_permissions_out} COMMAND ${test_permissions_out})
+set(test_permissions_out ${test_permissions_out} PARENT_SCOPE)

+ 1 - 0
doc/Fileformats.md

@@ -81,6 +81,7 @@ __Exporters__:
 - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
 - ASSBIN
 - STEP
+- [PBRTv4](https://github.com/mmp/pbrt-v4)
 - glTF 1.0 (partial)
 - glTF 2.0 (partial)
 - 3MF ( experimental )

+ 1 - 1
include/assimp/DefaultIOStream.h

@@ -119,7 +119,7 @@ private:
 AI_FORCE_INLINE
 DefaultIOStream::DefaultIOStream() AI_NO_EXCEPT
 : mFile(nullptr)
-, mFilename("")
+, mFilename()
 , mCachedSize(SIZE_MAX) {
     // empty
 }

+ 1 - 1
include/assimp/IOSystem.hpp

@@ -294,7 +294,7 @@ bool IOSystem::PushDirectory( const std::string &path ) {
 AI_FORCE_INLINE
 const std::string &IOSystem::CurrentDirectory() const {
     if ( m_pathStack.empty() ) {
-        static const std::string Dummy("");
+        static const std::string Dummy;
         return Dummy;
     }
     return m_pathStack[ m_pathStack.size()-1 ];

+ 1 - 1
include/assimp/Importer.hpp

@@ -286,7 +286,7 @@ public:
      * @see GetPropertyInteger()
      */
     std::string GetPropertyString(const char *szName,
-            const std::string &sErrorReturn = "") const;
+            const std::string &sErrorReturn = std::string()) const;
 
     // -------------------------------------------------------------------
     /** Get a matrix configuration property

+ 1 - 1
include/assimp/XmlParser.h

@@ -239,7 +239,7 @@ public:
     }
 
     static inline bool getValueAsString( XmlNode &node, std::string &text ) {
-        text = "";
+        text = std::string();
         if (node.empty()) {
             return false;
         }

+ 8 - 3
include/assimp/postprocess.h

@@ -209,9 +209,14 @@ enum aiPostProcessSteps
     /** <hr>Removes the node graph and pre-transforms all vertices with
     * the local transformation matrices of their nodes.
     *
-    * The output scene still contains nodes, however there is only a
-    * root node with children, each one referencing only one mesh,
-    * and each mesh referencing one material. For rendering, you can
+    * If the resulting scene can be reduced to a single mesh, with a single
+    * material, no lights, and no cameras, then the output scene will contain
+    * only a root node (with no children) that references the single mesh. 
+    * Otherwise, the output scene will be reduced to a root node with a single
+    * level of child nodes, each one referencing one mesh, and each mesh 
+    * referencing one material. 
+    *
+    * In either case, for rendering, you can
     * simply render all meshes in order - you don't need to pay
     * attention to local transformations and the node hierarchy.
     * Animations are removed during this step.

+ 5 - 4
tools/assimp_cmd/ImageExtractor.cpp

@@ -130,8 +130,9 @@ int SaveAsBMP(FILE *file, const aiTexel *data, unsigned int width, unsigned int
             s[0] = t->b;
             s[1] = t->g;
             s[2] = t->r;
-            if (4 == numc)
+            if (4 == numc) {
                 s[3] = t->a;
+            }
         }
     }
 
@@ -296,7 +297,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
 
         // check whether the requested texture is existing
         if (texIdx >= scene->mNumTextures) {
-            ::printf("assimp extract: Texture %i requested, but there are just %i textures\n",
+            ::printf("assimp extract: Texture %u requested, but there are just %i textures\n",
                     texIdx, scene->mNumTextures);
             return AssimpCmdExtractError::TextureIndexIsOutOfRange;
         }
@@ -325,7 +326,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
         // if the texture is a compressed one, we'll export
         // it to its native file format
         if (!tex->mHeight) {
-            printf("assimp extract: Texture %i is compressed (%s). Writing native file format.\n",
+            printf("assimp extract: Texture %u is compressed (%s). Writing native file format.\n",
                     i, tex->achFormatHint);
 
             // modify file extension
@@ -350,7 +351,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
         }
         ::fclose(p);
 
-        printf("assimp extract: Wrote texture %i to %s\n", i, out_cpy.c_str());
+        printf("assimp extract: Wrote texture %u to %s\n", i, out_cpy.c_str());
         if (texIdx != 0xffffffff) {
             return m;
         }

Some files were not shown because too many files changed in this diff