浏览代码

Merge branch 'master' into change_file_encoding

Kim Kulling 4 年之前
父节点
当前提交
e5417ea41f
共有 39 个文件被更改,包括 337 次插入405 次删除
  1. 1 1
      code/AssetLib/3DS/3DSLoader.cpp
  2. 7 7
      code/AssetLib/3MF/D3MFExporter.cpp
  3. 4 4
      code/AssetLib/3MF/D3MFImporter.cpp
  4. 1 1
      code/AssetLib/AC/ACLoader.h
  5. 3 1
      code/AssetLib/AMF/AMFImporter.cpp
  6. 1 1
      code/AssetLib/AMF/AMFImporter_Postprocess.cpp
  7. 4 4
      code/AssetLib/Collada/ColladaExporter.cpp
  8. 3 3
      code/AssetLib/Collada/ColladaHelper.cpp
  9. 3 3
      code/AssetLib/Collada/ColladaParser.cpp
  10. 1 1
      code/AssetLib/FBX/FBXBinaryTokenizer.cpp
  11. 7 7
      code/AssetLib/FBX/FBXConverter.cpp
  12. 2 2
      code/AssetLib/FBX/FBXExportNode.cpp
  13. 1 1
      code/AssetLib/MMD/MMDPmxParser.cpp
  14. 120 216
      code/AssetLib/Ogre/OgreMaterial.cpp
  15. 7 52
      code/AssetLib/Ogre/OgreParsingUtils.h
  16. 3 3
      code/AssetLib/Ogre/OgreXmlSerializer.cpp
  17. 9 5
      code/AssetLib/STEPParser/STEPFileReader.cpp
  18. 6 2
      code/AssetLib/Step/StepExporter.cpp
  19. 1 1
      code/AssetLib/X/XFileParser.cpp
  20. 17 17
      code/AssetLib/glTF/glTFAsset.inl
  21. 1 1
      code/AssetLib/glTF/glTFExporter.cpp
  22. 1 1
      code/AssetLib/glTF/glTFImporter.cpp
  23. 1 1
      code/AssetLib/glTF2/glTF2Asset.h
  24. 6 6
      code/AssetLib/glTF2/glTF2Asset.inl
  25. 2 2
      code/AssetLib/glTF2/glTF2Exporter.cpp
  26. 1 1
      code/Common/BaseImporter.cpp
  27. 2 3
      code/Common/Importer.cpp
  28. 3 3
      code/PostProcessing/ComputeUVMappingProcess.cpp
  29. 1 1
      code/PostProcessing/EmbedTexturesProcess.cpp
  30. 4 0
      contrib/unzip/crypt.c
  31. 8 0
      include/assimp/Exceptional.h
  32. 2 11
      include/assimp/ParsingUtils.h
  33. 10 15
      include/assimp/StringComparison.h
  34. 80 23
      include/assimp/StringUtils.h
  35. 8 0
      include/assimp/importerdesc.h
  36. 1 1
      include/assimp/metadata.h
  37. 2 2
      test/unit/utStringUtils.cpp
  38. 2 1
      tools/assimp_cmd/Export.cpp
  39. 1 1
      tools/assimp_cmd/ImageExtractor.cpp

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

@@ -324,7 +324,7 @@ void Discreet3DSImporter::ParseObjectChunk() {
     case Discreet3DS::CHUNK_MAT_MATERIAL:
 
         // Add a new material to the list
-        mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + to_string(mScene->mMaterials.size()))));
+        mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + ai_to_string(mScene->mMaterials.size()))));
         ParseMaterialChunk();
         break;
 

+ 7 - 7
code/AssetLib/3MF/D3MFExporter.cpp

@@ -237,7 +237,7 @@ void D3MFExporter::writeBaseMaterials() {
         aiMaterial *mat = mScene->mMaterials[i];
         aiString name;
         if (mat->Get(AI_MATKEY_NAME, name) != aiReturn_SUCCESS) {
-            strName = "basemat_" + to_string(i);
+            strName = "basemat_" + ai_to_string(i);
         } else {
             strName = name.C_Str();
         }
@@ -248,7 +248,7 @@ void D3MFExporter::writeBaseMaterials() {
             // rgbs %
             if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) {
 
-                hexDiffuseColor = Rgba2Hex(
+                hexDiffuseColor = ai_rgba2hex(
                         (int)((ai_real)color.r) * 255,
                         (int)((ai_real)color.g) * 255,
                         (int)((ai_real)color.b) * 255,
@@ -257,13 +257,13 @@ void D3MFExporter::writeBaseMaterials() {
 
             } else {
                 hexDiffuseColor = "#";
-                tmp = DecimalToHexa((ai_real)color.r);
+                tmp = ai_decimal_to_hexa((ai_real)color.r);
                 hexDiffuseColor += tmp;
-                tmp = DecimalToHexa((ai_real)color.g);
+                tmp = ai_decimal_to_hexa((ai_real)color.g);
                 hexDiffuseColor += tmp;
-                tmp = DecimalToHexa((ai_real)color.b);
+                tmp = ai_decimal_to_hexa((ai_real)color.b);
                 hexDiffuseColor += tmp;
-                tmp = DecimalToHexa((ai_real)color.a);
+                tmp = ai_decimal_to_hexa((ai_real)color.a);
                 hexDiffuseColor += tmp;
             }
         } else {
@@ -339,7 +339,7 @@ void D3MFExporter::writeFaces(aiMesh *mesh, unsigned int matIdx) {
         aiFace &currentFace = mesh->mFaces[i];
         mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\""
                      << currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2]
-                     << "\" pid=\"1\" p1=\"" + to_string(matIdx) + "\" />";
+                     << "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />";
         mModelOutput << std::endl;
     }
     mModelOutput << "</" << XmlTag::triangles << ">";

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

@@ -116,7 +116,7 @@ public:
 
     Object(int id) :
             Resource(id),
-            mName (std::string("Object_") + to_string(id)){}
+            mName(std::string("Object_") + ai_to_string(id)) {}
 
     virtual ResourceType getType() {
         return ResourceType::RT_Object;
@@ -321,7 +321,7 @@ private:
         bool hasPid = getNodeAttribute(node, D3MF::XmlTag::pid, pid);
         bool hasPindex = getNodeAttribute(node, D3MF::XmlTag::pindex, pindex);
 
-        std::string idStr = to_string(id);
+        std::string idStr = ai_to_string(id);
 
         if (!hasId) {
             return;
@@ -531,7 +531,7 @@ private:
         bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
 
         std::string stdMaterialName;
-        std::string strId(to_string(basematerialsId));
+        std::string strId(ai_to_string(basematerialsId));
         stdMaterialName += "id";
         stdMaterialName += strId;
         stdMaterialName += "_";
@@ -539,7 +539,7 @@ private:
             stdMaterialName += std::string(name);
         } else {
             stdMaterialName += "basemat_";
-            stdMaterialName += to_string(mMaterialCount - basematerialsId);
+            stdMaterialName += ai_to_string(mMaterialCount - basematerialsId);
         }
 
         aiString assimpMaterialName(stdMaterialName);

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

@@ -116,7 +116,7 @@ public:
             Mask = 0xf,
         };
 
-        inline const uint8_t GetType() const { return (flags & Mask); }
+        inline uint8_t GetType() const { return (flags & Mask); }
     };
 
     // Represents an AC3D object

+ 3 - 1
code/AssetLib/AMF/AMFImporter.cpp

@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/fast_atof.h>
+#include <assimp/StringUtils.h>
 
 // Header files, stdlib.
 #include <memory>
@@ -306,7 +307,8 @@ void AMFImporter::ParseNode_Root() {
         throw DeadlyImportError("Root node \"amf\" not found.");
     }
     XmlNode node = *root;
-    mUnit = node.attribute("unit").as_string();
+    mUnit = ai_str_tolower(std::string(node.attribute("unit").as_string()));
+    
     mVersion = node.attribute("version").as_string();
 
     // Read attributes for node <amf>.

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

@@ -873,7 +873,7 @@ nl_clean_loop:
         pScene->mNumMaterials = static_cast<unsigned int>(mTexture_Converted.size());
         pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
         for (const SPP_Texture &tex_convd : mTexture_Converted) {
-            const aiString texture_id(AI_EMBEDDED_TEXNAME_PREFIX + to_string(idx));
+            const aiString texture_id(AI_EMBEDDED_TEXNAME_PREFIX + ai_to_string(idx));
             const int mode = aiTextureOp_Multiply;
             const int repeat = tex_convd.Tiled ? 1 : 0;
 

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

@@ -129,7 +129,7 @@ inline std::string MakeUniqueId(const std::unordered_set<std::string> &idSet, co
         // Select a number to append
         size_t idnum = 1;
         do {
-            result = idPrefix + '_' + to_string(idnum) + postfix;
+            result = idPrefix + '_' + ai_to_string(idnum) + postfix;
             ++idnum;
         } while (!IsUniqueId(idSet, result));
     }
@@ -1017,7 +1017,7 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
     // texture coords
     for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
         if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) {
-            WriteFloatArray(geometryId + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
+            WriteFloatArray(geometryId + "-tex" + ai_to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
                     (ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices);
         }
     }
@@ -1025,7 +1025,7 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
     // vertex colors
     for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
         if (mesh->HasVertexColors(static_cast<unsigned int>(a)))
-            WriteFloatArray(geometryId + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices);
+            WriteFloatArray(geometryId + "-color" + ai_to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices);
     }
 
     // assemble vertex structure
@@ -1724,7 +1724,7 @@ ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType t
         case AiObjectType::Camera: idStr = std::string("camera_"); break;
         case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
         }
-        idStr.append(to_string(index));
+        idStr.append(ai_to_string(index));
     } else {
         idStr = XMLIDEncode(name);
     }

+ 3 - 3
code/AssetLib/Collada/ColladaHelper.cpp

@@ -80,16 +80,16 @@ void ToCamelCase(std::string &text) {
         return;
     // Capitalise first character
     auto it = text.begin();
-    (*it) = ToUpper(*it);
+    (*it) = ai_toupper(*it);
     ++it;
     for (/*started above*/; it != text.end(); /*iterated below*/) {
         if ((*it) == '_') {
             it = text.erase(it);
             if (it != text.end())
-                (*it) = ToUpper(*it);
+                (*it) = ai_toupper(*it);
         } else {
             // Make lower case
-            (*it) = ToLower(*it);
+            (*it) = ai_tolower(*it);
             ++it;
         }
     }

+ 3 - 3
code/AssetLib/Collada/ColladaParser.cpp

@@ -372,7 +372,7 @@ void ColladaParser::ReadMetaDataItem(XmlNode &node, StringMetaData &metadata) {
         return;
     }
 
-    trim(v);
+    v = ai_trim(v);
     aiString aistr;
     aistr.Set(v);
 
@@ -397,7 +397,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
     std::string animName;
     if (!XmlParser::getStdStrAttribute(node, "name", animName)) {
         if (!XmlParser::getStdStrAttribute( node, "id", animName )) {
-            animName = std::string("animation_") + to_string(mAnimationClipLibrary.size());
+            animName = std::string("animation_") + ai_to_string(mAnimationClipLibrary.size());
         }
     }
 
@@ -1415,7 +1415,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
     XmlParser::getUIntAttribute(node, "count", count);
     std::string v;
     XmlParser::getValueAsString(node, v);
-    trim(v);
+    v = ai_trim(v);
     const char *content = v.c_str();
 
     // read values and store inside an array in the data library

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

@@ -473,7 +473,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
     catch (const DeadlyImportError& e)
     {
         if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) {
-            throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", to_string(version), ") of the FBX format. (", e.what(), ")");
+            throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", ai_to_string(version), ") of the FBX format. (", e.what(), ")");
         }
         throw;
     }

+ 7 - 7
code/AssetLib/FBX/FBXConverter.cpp

@@ -3440,7 +3440,7 @@ void FBXConverter::ConvertGlobalSettings() {
     mSceneOut->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart());
     mSceneOut->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop());
     mSceneOut->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
-    mSceneOut->mMetaData->Set(15, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(to_string(doc.FBXVersion())));
+    mSceneOut->mMetaData->Set(15, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(ai_to_string(doc.FBXVersion())));
     if (hasGenerator) {
         mSceneOut->mMetaData->Set(16, AI_METADATA_SOURCE_GENERATOR, aiString(doc.Creator()));
     }
@@ -3454,42 +3454,42 @@ void FBXConverter::TransferDataToScene() {
     // many C++ users seem to know this, so pointing it out to avoid
     // confusion why this code works.
 
-    if (mMeshes.size()) {
+    if (!mMeshes.empty()) {
         mSceneOut->mMeshes = new aiMesh *[mMeshes.size()]();
         mSceneOut->mNumMeshes = static_cast<unsigned int>(mMeshes.size());
 
         std::swap_ranges(mMeshes.begin(), mMeshes.end(), mSceneOut->mMeshes);
     }
 
-    if (materials.size()) {
+    if (!materials.empty()) {
         mSceneOut->mMaterials = new aiMaterial *[materials.size()]();
         mSceneOut->mNumMaterials = static_cast<unsigned int>(materials.size());
 
         std::swap_ranges(materials.begin(), materials.end(), mSceneOut->mMaterials);
     }
 
-    if (animations.size()) {
+    if (!animations.empty()) {
         mSceneOut->mAnimations = new aiAnimation *[animations.size()]();
         mSceneOut->mNumAnimations = static_cast<unsigned int>(animations.size());
 
         std::swap_ranges(animations.begin(), animations.end(), mSceneOut->mAnimations);
     }
 
-    if (lights.size()) {
+    if (!lights.empty()) {
         mSceneOut->mLights = new aiLight *[lights.size()]();
         mSceneOut->mNumLights = static_cast<unsigned int>(lights.size());
 
         std::swap_ranges(lights.begin(), lights.end(), mSceneOut->mLights);
     }
 
-    if (cameras.size()) {
+    if (!cameras.empty()) {
         mSceneOut->mCameras = new aiCamera *[cameras.size()]();
         mSceneOut->mNumCameras = static_cast<unsigned int>(cameras.size());
 
         std::swap_ranges(cameras.begin(), cameras.end(), mSceneOut->mCameras);
     }
 
-    if (textures.size()) {
+    if (!textures.empty()) {
         mSceneOut->mTextures = new aiTexture *[textures.size()]();
         mSceneOut->mNumTextures = static_cast<unsigned int>(textures.size());
 

+ 2 - 2
code/AssetLib/FBX/FBXExportNode.cpp

@@ -426,7 +426,7 @@ void FBX::Node::WritePropertyNodeAscii(
     char buffer[32];
     FBX::Node node(name);
     node.Begin(s, false, indent);
-    std::string vsize = to_string(v.size());
+    std::string vsize = ai_to_string(v.size());
     // *<size> {
     s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
     // indent + 1
@@ -462,7 +462,7 @@ void FBX::Node::WritePropertyNodeAscii(
     char buffer[32];
     FBX::Node node(name);
     node.Begin(s, false, indent);
-    std::string vsize = to_string(v.size());
+    std::string vsize = ai_to_string(v.size());
     // *<size> {
     s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
     // indent + 1

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

@@ -524,7 +524,7 @@ namespace pmx
 		if (version != 2.0f && version != 2.1f)
 		{
 			std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl;
-            throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but ", to_string(version));
+            throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but ", ai_to_string(version));
     }
 		this->setting.Read(stream);
 

+ 120 - 216
code/AssetLib/Ogre/OgreMaterial.cpp

@@ -40,45 +40,38 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-
-
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 
 #include "OgreImporter.h"
+#include <assimp/StringUtils.h>
 #include <assimp/TinyFormatter.h>
+#include <assimp/fast_atof.h>
 #include <assimp/material.h>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
-#include <assimp/fast_atof.h>
 
-#include <vector>
-#include <sstream>
 #include <memory>
+#include <sstream>
+#include <vector>
 
 using namespace std;
 
-namespace Assimp
-{
-namespace Ogre
-{
+namespace Assimp {
+namespace Ogre {
 
-static const string partComment    = "//";
+static const string partComment = "//";
 static const string partBlockStart = "{";
-static const string partBlockEnd   = "}";
+static const string partBlockEnd = "}";
 
-void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh)
-{
-    std::vector<aiMaterial*> materials;
+void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh) {
+    std::vector<aiMaterial *> materials;
 
     // Create materials that can be found and parsed via the IOSystem.
-    for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
-    {
+    for (size_t i = 0, len = mesh->NumSubMeshes(); i < len; ++i) {
         SubMesh *submesh = mesh->GetSubMesh(i);
-        if (submesh && !submesh->materialRef.empty())
-        {
+        if (submesh && !submesh->materialRef.empty()) {
             aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
-            if (material)
-            {
+            if (material) {
                 submesh->materialIndex = static_cast<int>(materials.size());
                 materials.push_back(material);
             }
@@ -88,19 +81,15 @@ void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIO
     AssignMaterials(pScene, materials);
 }
 
-void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh)
-{
-    std::vector<aiMaterial*> materials;
+void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh) {
+    std::vector<aiMaterial *> materials;
 
     // Create materials that can be found and parsed via the IOSystem.
-    for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
-    {
-        SubMeshXml *submesh = mesh->GetSubMesh( static_cast<uint16_t>(i));
-        if (submesh && !submesh->materialRef.empty())
-        {
+    for (size_t i = 0, len = mesh->NumSubMeshes(); i < len; ++i) {
+        SubMeshXml *submesh = mesh->GetSubMesh(static_cast<uint16_t>(i));
+        if (submesh && !submesh->materialRef.empty()) {
             aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
-            if (material)
-            {
+            if (material) {
                 submesh->materialIndex = static_cast<int>(materials.size());
                 materials.push_back(material);
             }
@@ -110,20 +99,17 @@ void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIO
     AssignMaterials(pScene, materials);
 }
 
-void OgreImporter::AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials)
-{
+void OgreImporter::AssignMaterials(aiScene *pScene, std::vector<aiMaterial *> &materials) {
     pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
-    if (pScene->mNumMaterials > 0)
-    {
-        pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
-        for(size_t i=0;i<pScene->mNumMaterials; ++i) {
+    if (pScene->mNumMaterials > 0) {
+        pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
+        for (size_t i = 0; i < pScene->mNumMaterials; ++i) {
             pScene->mMaterials[i] = materials[i];
         }
     }
 }
 
-aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string &materialName)
-{
+aiMaterial *OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string &materialName) {
     if (materialName.empty()) {
         return 0;
     }
@@ -169,24 +155,21 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
             potentialFiles.push_back(m_userDefinedMaterialLibFile);
 
         IOStream *materialFile = 0;
-        for(size_t i=0; i<potentialFiles.size(); ++i)
-        {
+        for (size_t i = 0; i < potentialFiles.size(); ++i) {
             materialFile = pIOHandler->Open(potentialFiles[i]);
             if (materialFile) {
                 break;
             }
-            ASSIMP_LOG_VERBOSE_DEBUG_F( "Source file for material '", materialName, "' ", potentialFiles[i], " does not exist");
+            ASSIMP_LOG_VERBOSE_DEBUG_F("Source file for material '", materialName, "' ", potentialFiles[i], " does not exist");
         }
-        if (!materialFile)
-        {
-            ASSIMP_LOG_ERROR_F( "Failed to find source file for material '", materialName, "'");
+        if (!materialFile) {
+            ASSIMP_LOG_ERROR_F("Failed to find source file for material '", materialName, "'");
             return 0;
         }
 
         std::unique_ptr<IOStream> stream(materialFile);
-        if (stream->FileSize() == 0)
-        {
-            ASSIMP_LOG_WARN_F( "Source file for material '", materialName, "' is empty (size is 0 bytes)");
+        if (stream->FileSize() == 0) {
+            ASSIMP_LOG_WARN_F("Source file for material '", materialName, "' is empty (size is 0 bytes)");
             return 0;
         }
 
@@ -214,48 +197,41 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
     string linePart;
     ss >> linePart;
 
-    const string partMaterial   = "material";
-    const string partTechnique  = "technique";
+    const string partMaterial = "material";
+    const string partTechnique = "technique";
 
-    while(!ss.eof())
-    {
+    while (!ss.eof()) {
         // Skip commented lines
-        if (linePart == partComment)
-        {
+        if (linePart == partComment) {
             NextAfterNewLine(ss, linePart);
             continue;
         }
-        if (linePart != partMaterial)
-        {
+        if (linePart != partMaterial) {
             ss >> linePart;
             continue;
         }
 
         ss >> linePart;
-        if (linePart != materialName)
-        {
+        if (linePart != materialName) {
             ss >> linePart;
             continue;
         }
 
         NextAfterNewLine(ss, linePart);
-        if (linePart != partBlockStart)
-        {
-            ASSIMP_LOG_ERROR_F( "Invalid material: block start missing near index ", ss.tellg());
+        if (linePart != partBlockStart) {
+            ASSIMP_LOG_ERROR_F("Invalid material: block start missing near index ", ss.tellg());
             return material;
         }
 
         ASSIMP_LOG_VERBOSE_DEBUG_F("material '", materialName, "'");
 
-        while(linePart != partBlockEnd)
-        {
+        while (linePart != partBlockEnd) {
             // Proceed to the first technique
             ss >> linePart;
 
-            if (linePart == partTechnique)
-            {
-                string techniqueName = SkipLine(ss);
-                ReadTechnique(Trim(techniqueName), ss, material);
+            if (linePart == partTechnique) {
+                std::string techniqueName = SkipLine(ss);
+                ReadTechnique(ai_trim(techniqueName), ss, material);
             }
 
             // Read information from a custom material
@@ -264,71 +240,51 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
                 parent texture unit name in your cloned material.
                 This is not yet supported and below code is probably some hack from the original
                 author of this Ogre importer. Should be removed? */
-            if (linePart=="set")
-            {
+            if (linePart == "set") {
                 ss >> linePart;
-                if (linePart=="$specular")//todo load this values:
-                {
-                }
-                else if (linePart=="$diffuse")
-                {
-                }
-                else if (linePart=="$ambient")
-                {
-                }
-                else if (linePart=="$colormap")
+                if (linePart == "$specular") //todo load this values:
                 {
+                } else if (linePart == "$diffuse") {
+                } else if (linePart == "$ambient") {
+                } else if (linePart == "$colormap") {
                     ss >> linePart;
                     aiString cm(linePart);
                     material->AddProperty(&cm, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
-                }
-                else if (linePart=="$normalmap")
-                {
+                } else if (linePart == "$normalmap") {
                     ss >> linePart;
                     aiString nm(linePart);
                     material->AddProperty(&nm, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
-                }
-                else if (linePart=="$shininess_strength")
-                {
+                } else if (linePart == "$shininess_strength") {
                     ss >> linePart;
                     float Shininess = fast_atof(linePart.c_str());
                     material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
-                }
-                else if (linePart=="$shininess_exponent")
-                {
+                } else if (linePart == "$shininess_exponent") {
                     ss >> linePart;
                     float Shininess = fast_atof(linePart.c_str());
                     material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
                 }
                 //Properties from Venetica:
-                else if (linePart=="$diffuse_map")
-                {
+                else if (linePart == "$diffuse_map") {
                     ss >> linePart;
-                    if (linePart[0] == '"')// "file" -> file
-                        linePart = linePart.substr(1, linePart.size()-2);
+                    if (linePart[0] == '"') // "file" -> file
+                        linePart = linePart.substr(1, linePart.size() - 2);
                     aiString ts(linePart);
                     material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
-                }
-                else if (linePart=="$specular_map")
-                {
+                } else if (linePart == "$specular_map") {
                     ss >> linePart;
-                    if (linePart[0] == '"')// "file" -> file
-                        linePart = linePart.substr(1, linePart.size()-2);
+                    if (linePart[0] == '"') // "file" -> file
+                        linePart = linePart.substr(1, linePart.size() - 2);
                     aiString ts(linePart);
                     material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
-                }
-                else if (linePart=="$normal_map")
-                {
+                } else if (linePart == "$normal_map") {
                     ss >> linePart;
-                    if (linePart[0]=='"')// "file" -> file
-                        linePart = linePart.substr(1, linePart.size()-2);
+                    if (linePart[0] == '"') // "file" -> file
+                        linePart = linePart.substr(1, linePart.size() - 2);
                     aiString ts(linePart);
                     material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
-                }
-                else if (linePart=="$light_map")
-                {
+                } else if (linePart == "$light_map") {
                     ss >> linePart;
-                    if (linePart[0]=='"') {
+                    if (linePart[0] == '"') {
                         linePart = linePart.substr(1, linePart.size() - 2);
                     }
                     aiString ts(linePart);
@@ -342,216 +298,166 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
     return material;
 }
 
-bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream &ss, aiMaterial *material)
-{
+bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream &ss, aiMaterial *material) {
     string linePart;
     ss >> linePart;
 
-    if (linePart != partBlockStart)
-    {
-        ASSIMP_LOG_ERROR_F( "Invalid material: Technique block start missing near index ", ss.tellg());
+    if (linePart != partBlockStart) {
+        ASSIMP_LOG_ERROR_F("Invalid material: Technique block start missing near index ", ss.tellg());
         return false;
     }
 
     ASSIMP_LOG_VERBOSE_DEBUG_F(" technique '", techniqueName, "'");
 
-    const string partPass  = "pass";
+    const string partPass = "pass";
 
-    while(linePart != partBlockEnd)
-    {
+    while (linePart != partBlockEnd) {
         ss >> linePart;
 
         // Skip commented lines
-        if (linePart == partComment)
-        {
+        if (linePart == partComment) {
             SkipLine(ss);
             continue;
         }
 
         /// @todo Techniques have other attributes than just passes.
-        if (linePart == partPass)
-        {
+        if (linePart == partPass) {
             string passName = SkipLine(ss);
-            ReadPass(Trim(passName), ss, material);
+            ReadPass(ai_trim(passName), ss, material);
         }
     }
     return true;
 }
 
-bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMaterial *material)
-{
+bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMaterial *material) {
     string linePart;
     ss >> linePart;
 
-    if (linePart != partBlockStart)
-    {
-        ASSIMP_LOG_ERROR_F( "Invalid material: Pass block start missing near index ", ss.tellg());
+    if (linePart != partBlockStart) {
+        ASSIMP_LOG_ERROR_F("Invalid material: Pass block start missing near index ", ss.tellg());
         return false;
     }
 
     ASSIMP_LOG_VERBOSE_DEBUG_F("  pass '", passName, "'");
 
-    const string partAmbient     = "ambient";
-    const string partDiffuse     = "diffuse";
-    const string partSpecular    = "specular";
-    const string partEmissive    = "emissive";
+    const string partAmbient = "ambient";
+    const string partDiffuse = "diffuse";
+    const string partSpecular = "specular";
+    const string partEmissive = "emissive";
     const string partTextureUnit = "texture_unit";
 
-    while(linePart != partBlockEnd)
-    {
+    while (linePart != partBlockEnd) {
         ss >> linePart;
 
         // Skip commented lines
-        if (linePart == partComment)
-        {
+        if (linePart == partComment) {
             SkipLine(ss);
             continue;
         }
 
         // Colors
         /// @todo Support alpha via aiColor4D.
-        if (linePart == partAmbient || linePart == partDiffuse || linePart == partSpecular || linePart == partEmissive)
-        {
+        if (linePart == partAmbient || linePart == partDiffuse || linePart == partSpecular || linePart == partEmissive) {
             float r, g, b;
             ss >> r >> g >> b;
             const aiColor3D color(r, g, b);
 
-            ASSIMP_LOG_VERBOSE_DEBUG_F( "   ", linePart, " ", r, " ", g, " ", b);
+            ASSIMP_LOG_VERBOSE_DEBUG_F("   ", linePart, " ", r, " ", g, " ", b);
 
-            if (linePart == partAmbient)
-            {
+            if (linePart == partAmbient) {
                 material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT);
-            }
-            else if (linePart == partDiffuse)
-            {
+            } else if (linePart == partDiffuse) {
                 material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
-            }
-            else if (linePart == partSpecular)
-            {
+            } else if (linePart == partSpecular) {
                 material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR);
-            }
-            else if (linePart == partEmissive)
-            {
+            } else if (linePart == partEmissive) {
                 material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE);
             }
-        }
-        else if (linePart == partTextureUnit)
-        {
+        } else if (linePart == partTextureUnit) {
             string textureUnitName = SkipLine(ss);
-            ReadTextureUnit(Trim(textureUnitName), ss, material);
+            ReadTextureUnit(ai_trim(textureUnitName), ss, material);
         }
     }
     return true;
 }
 
-bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstream &ss, aiMaterial *material)
-{
+bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstream &ss, aiMaterial *material) {
     string linePart;
     ss >> linePart;
 
-    if (linePart != partBlockStart)
-    {
-        ASSIMP_LOG_ERROR_F( "Invalid material: Texture unit block start missing near index ", ss.tellg());
+    if (linePart != partBlockStart) {
+        ASSIMP_LOG_ERROR_F("Invalid material: Texture unit block start missing near index ", ss.tellg());
         return false;
     }
 
     ASSIMP_LOG_VERBOSE_DEBUG_F("   texture_unit '", textureUnitName, "'");
 
-    const string partTexture      = "texture";
+    const string partTexture = "texture";
     const string partTextCoordSet = "tex_coord_set";
-    const string partColorOp      = "colour_op";
+    const string partColorOp = "colour_op";
 
     aiTextureType textureType = aiTextureType_NONE;
     std::string textureRef;
     int uvCoord = 0;
 
-    while(linePart != partBlockEnd)
-    {
+    while (linePart != partBlockEnd) {
         ss >> linePart;
 
         // Skip commented lines
-        if (linePart == partComment)
-        {
+        if (linePart == partComment) {
             SkipLine(ss);
             continue;
         }
 
-        if (linePart == partTexture)
-        {
+        if (linePart == partTexture) {
             ss >> linePart;
             textureRef = linePart;
 
             // User defined Assimp config property to detect texture type from filename.
-            if (m_detectTextureTypeFromFilename)
-            {
+            if (m_detectTextureTypeFromFilename) {
                 size_t posSuffix = textureRef.find_last_of(".");
                 size_t posUnderscore = textureRef.find_last_of("_");
 
-                if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore)
-                {
-                    string identifier = Ogre::ToLower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));
-                    ASSIMP_LOG_VERBOSE_DEBUG_F( "Detecting texture type from filename postfix '", identifier, "'");
+                if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) {
+                    string identifier = ai_str_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));
+                    ASSIMP_LOG_VERBOSE_DEBUG_F("Detecting texture type from filename postfix '", identifier, "'");
 
-                    if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap")
-                    {
+                    if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") {
                         textureType = aiTextureType_NORMALS;
-                    }
-                    else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap")
-                    {
+                    } else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap") {
                         textureType = aiTextureType_SPECULAR;
-                    }
-                    else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion")
-                    {
+                    } else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion") {
                         textureType = aiTextureType_LIGHTMAP;
-                    }
-                    else if (identifier == "_disp" || identifier == "_displacement")
-                    {
+                    } else if (identifier == "_disp" || identifier == "_displacement") {
                         textureType = aiTextureType_DISPLACEMENT;
-                    }
-                    else
-                    {
+                    } else {
                         textureType = aiTextureType_DIFFUSE;
                     }
-                }
-                else
-                {
+                } else {
                     textureType = aiTextureType_DIFFUSE;
                 }
             }
             // Detect from texture unit name. This cannot be too broad as
             // authors might give names like "LightSaber" or "NormalNinja".
-            else
-            {
-                string unitNameLower = Ogre::ToLower(textureUnitName);
-                if (unitNameLower.find("normalmap") != string::npos)
-                {
+            else {
+                string unitNameLower = ai_str_tolower(textureUnitName);
+                if (unitNameLower.find("normalmap") != string::npos) {
                     textureType = aiTextureType_NORMALS;
-                }
-                else if (unitNameLower.find("specularmap") != string::npos)
-                {
+                } else if (unitNameLower.find("specularmap") != string::npos) {
                     textureType = aiTextureType_SPECULAR;
-                }
-                else if (unitNameLower.find("lightmap") != string::npos)
-                {
+                } else if (unitNameLower.find("lightmap") != string::npos) {
                     textureType = aiTextureType_LIGHTMAP;
-                }
-                else if (unitNameLower.find("displacementmap") != string::npos)
-                {
+                } else if (unitNameLower.find("displacementmap") != string::npos) {
                     textureType = aiTextureType_DISPLACEMENT;
-                }
-                else
-                {
+                } else {
                     textureType = aiTextureType_DIFFUSE;
                 }
             }
-        }
-        else if (linePart == partTextCoordSet)
-        {
+        } else if (linePart == partTextCoordSet) {
             ss >> uvCoord;
         }
         /// @todo Implement
-        else if(linePart == partColorOp)
-        {
+        else if (linePart == partColorOp) {
             /*
             ss >> linePart;
             if("replace"==linePart)//I don't think, assimp has something for this...
@@ -566,22 +472,20 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
         }
     }
 
-    if (textureRef.empty())
-    {
+    if (textureRef.empty()) {
         ASSIMP_LOG_WARN("Texture reference is empty, ignoring texture_unit.");
         return false;
     }
-    if (textureType == aiTextureType_NONE)
-    {
-        ASSIMP_LOG_WARN("Failed to detect texture type for '" + textureRef  + "', ignoring texture_unit.");
+    if (textureType == aiTextureType_NONE) {
+        ASSIMP_LOG_WARN("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit.");
         return false;
     }
 
     unsigned int textureTypeIndex = m_textures[textureType];
     m_textures[textureType]++;
 
-    ASSIMP_LOG_VERBOSE_DEBUG_F( "    texture '", textureRef, "' type ", textureType,
-        " index ", textureTypeIndex, " UV ", uvCoord);
+    ASSIMP_LOG_VERBOSE_DEBUG_F("    texture '", textureRef, "' type ", textureType,
+            " index ", textureTypeIndex, " UV ", uvCoord);
 
     aiString assimpTextureRef(textureRef);
     material->AddProperty(&assimpTextureRef, AI_MATKEY_TEXTURE(textureType, textureTypeIndex));
@@ -590,7 +494,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
     return true;
 }
 
-} // Ogre
-} // Assimp
+} // namespace Ogre
+} // namespace Assimp
 
 #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER

+ 7 - 52
code/AssetLib/Ogre/OgreParsingUtils.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -46,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 
 #include <assimp/ParsingUtils.h>
-#include <stdint.h>
+#include <cstdint>
 #include <algorithm>
 #include <cctype>
 #include <functional>
@@ -55,16 +54,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace Ogre {
 
-/// Returns a lower cased copy of @s.
-static AI_FORCE_INLINE std::string ToLower(const std::string &s) {
-    std::string lower(s);
-    std::transform(lower.begin(), lower.end(), lower.begin(), Assimp::ToLower<char>);
-
-    return lower;
-}
 
 /// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
-static AI_FORCE_INLINE bool EndsWith( const std::string &s, const std::string &suffix, bool caseSensitive = true) {
+static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) {
     if (s.empty() || suffix.empty()) {
         return false;
     } else if (s.length() < suffix.length()) {
@@ -72,7 +64,7 @@ static AI_FORCE_INLINE bool EndsWith( const std::string &s, const std::string &s
     }
 
     if (!caseSensitive) {
-        return EndsWith(ToLower(s), ToLower(suffix), true);
+        return EndsWith(ai_str_tolower(s), ai_str_tolower(suffix), true);
     }
 
     size_t len = suffix.length();
@@ -81,53 +73,16 @@ static AI_FORCE_INLINE bool EndsWith( const std::string &s, const std::string &s
     return (ASSIMP_stricmp(sSuffix, suffix) == 0);
 }
 
-// Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
-
-/// Trim from start
-static AI_FORCE_INLINE
-        std::string &
-        TrimLeft(std::string &s, bool newlines = true) {
-    if (!newlines) {
-        s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
-    } else {
-        s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
-    }
-    return s;
-}
-
-/// Trim from end
-static AI_FORCE_INLINE
-        std::string &
-        TrimRight(std::string &s, bool newlines = true) {
-    if (!newlines) {
-        s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(), s.end());
-    } else {
-        s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
-    }
-    return s;
-}
-
-/// Trim from both ends
-static AI_FORCE_INLINE
-        std::string &
-        Trim(std::string &s, bool newlines = true) {
-    return TrimLeft(TrimRight(s, newlines), newlines);
-}
-
-/// Skips a line from current @ss position until a newline. Returns the skipped part.
-static AI_FORCE_INLINE
-        std::string
-        SkipLine(std::stringstream &ss) {
+// Skips a line from current @ss position until a newline. Returns the skipped part.
+static inline std::string SkipLine(std::stringstream &ss) {
     std::string skipped;
     getline(ss, skipped);
     return skipped;
 }
 
-/// Skips a line and reads next element from @c ss to @c nextElement.
+// Skips a line and reads next element from @c ss to @c nextElement.
 /** @return Skipped line content until newline. */
-static AI_FORCE_INLINE
-        std::string
-        NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
+static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
     std::string skipped = SkipLine(ss);
     ss >> nextElement;
     return skipped;

+ 3 - 3
code/AssetLib/Ogre/OgreXmlSerializer.cpp

@@ -120,7 +120,7 @@ std::string OgreXmlSerializer::ReadAttribute<std::string>(XmlNode &xmlNode, cons
 
 template <>
 bool OgreXmlSerializer::ReadAttribute<bool>(XmlNode &xmlNode, const char *name) const {
-    std::string value = Ogre::ToLower(ReadAttribute<std::string>(xmlNode, name));
+    std::string value = ai_str_tolower(ReadAttribute<std::string>(xmlNode, name));
     if (ASSIMP_stricmp(value, "true") == 0) {
         return true;
     } else if (ASSIMP_stricmp(value, "false") == 0) {
@@ -529,7 +529,7 @@ XmlParserPtr OgreXmlSerializer::OpenXmlParser(Assimp::IOSystem *pIOHandler, cons
         throw DeadlyImportError("Failed to open skeleton file ", filename);
     }
 
-    XmlParserPtr xmlParser = XmlParserPtr(new XmlParser);
+    XmlParserPtr xmlParser = std::make_shared<XmlParser>();
     if (!xmlParser->parse(file.get())) {
         throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
     }
@@ -545,7 +545,7 @@ void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) {
 
     // Optional blend mode from root node
     if (XmlParser::hasAttribute(node, "blendmode")) {
-        skeleton->blendMode = (ToLower(ReadAttribute<std::string>(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
+        skeleton->blendMode = (ai_str_tolower(ReadAttribute<std::string>(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
     }
 
     for (XmlNode &currentNode : node.children()) {

+ 9 - 5
code/AssetLib/STEPParser/STEPFileReader.cpp

@@ -270,11 +270,15 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
         }
 
         std::string::size_type ns = n0;
-        do ++ns; while( IsSpace(s.at(ns)));
+        do {
+            ++ns;
+        } while (IsSpace(s.at(ns)));
         std::string::size_type ne = n1;
-        do --ne; while( IsSpace(s.at(ne)));
-        std::string type = s.substr(ns,ne-ns+1);
-        std::transform( type.begin(), type.end(), type.begin(), &Assimp::ToLower<char>  );
+        do {
+            --ne;
+        } while (IsSpace(s.at(ne)));
+        std::string type = s.substr(ns, ne - ns + 1);
+        type = ai_str_tolower(type);
         const char* sz = scheme.GetStaticStringForToken(type);
         if(sz) {
             const std::string::size_type szLen = n2-n1+1;
@@ -317,7 +321,7 @@ std::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& i
                 }
                 for(--t;IsSpace(*t);--t);
                 std::string s(cur,static_cast<size_t>(t-cur+1));
-                std::transform(s.begin(),s.end(),s.begin(),&ToLower<char> );
+                std::transform(s.begin(),s.end(),s.begin(),&ai_tolower<char> );
                 if (schema->IsKnownToken(s)) {
                     for(cur = t+1;*cur++ != '(';);
                     const std::shared_ptr<const EXPRESS::DataType> dt = Parse(cur);

+ 6 - 2
code/AssetLib/Step/StepExporter.cpp

@@ -302,6 +302,10 @@ void StepExporter::WriteFile()
             dv23.Normalize();
             dv31.Normalize();
             dv13.Normalize();
+            
+            aiVector3D dvY = dv12;
+            aiVector3D dvX = dvY ^ dv13;
+            dvX.Normalize();
 
             int pid1 = uniqueVerts.find(v1)->second;
             int pid2 = uniqueVerts.find(v2)->second;
@@ -337,8 +341,8 @@ void StepExporter::WriteFile()
             mOutput << "#" << sid+9 << "=PLANE('',#" << sid+10 << ")" << endstr;
             mOutput << "#" << sid+10 << "=AXIS2_PLACEMENT_3D('',#" << pid1 << ", #" << sid+11 << ",#" << sid+12 << ")" << endstr;
 
-            mOutput << "#" << sid+11 << "=DIRECTION('',(" << dv12.x << "," << dv12.y << "," << dv12.z << "))" << endstr;
-            mOutput << "#" << sid+12 << "=DIRECTION('',(" << dv13.x << "," << dv13.y << "," << dv13.z << "))" << endstr;
+            mOutput << "#" << sid + 11 << "=DIRECTION('',(" << dvX.x << "," << dvX.y << "," << dvX.z << "))" << endstr;
+            mOutput << "#" << sid + 12 << "=DIRECTION('',(" << dvY.x << "," << dvY.y << "," << dvY.z << "))" << endstr;
 
             mOutput << "#" << sid+13 << "=FACE_BOUND('',#" << sid+14 << ",.T.)" << endstr;
             mOutput << "#" << sid+14 << "=EDGE_LOOP('',(#" << sid+15 << ",#" << sid+16 << ",#" << sid+17 << "))" << endstr;

+ 1 - 1
code/AssetLib/X/XFileParser.cpp

@@ -693,7 +693,7 @@ void XFileParser::ParseDataObjectMaterial(Material *pMaterial) {
     std::string matName;
     readHeadOfDataObject(&matName);
     if (matName.empty())
-        matName = std::string("material") + to_string(mLineNumber);
+        matName = std::string("material") + ai_to_string(mLineNumber);
     pMaterial->mName = matName;
     pMaterial->mIsReference = false;
 

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

@@ -318,13 +318,13 @@ inline void Buffer::Read(Value &obj, Asset &r) {
             this->mData.reset(data, std::default_delete<uint8_t[]>());
 
             if (statedLength > 0 && this->byteLength != statedLength) {
-                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
-                                        " bytes, but found ", to_string(dataURI.dataLength));
+                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength),
+                        " bytes, but found ", ai_to_string(dataURI.dataLength));
             }
         } else { // assume raw data
             if (statedLength != dataURI.dataLength) {
-                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
-                                        " bytes, but found ", to_string(dataURI.dataLength));
+                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength),
+                        " bytes, but found ", ai_to_string(dataURI.dataLength));
             }
 
             this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>());
@@ -927,24 +927,24 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
     size_t size_coordindex = ifs.GetNCoordIndex() * 3; // See float attributes note.
 
     if (primitives[0].indices->count != size_coordindex)
-        throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (", to_string(size_coordindex),
-                                ") not equal to uncompressed (", to_string(primitives[0].indices->count), ").");
+        throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (", ai_to_string(size_coordindex),
+                ") not equal to uncompressed (", ai_to_string(primitives[0].indices->count), ").");
 
     size_coordindex *= sizeof(IndicesType);
     // Coordinates
     size_t size_coord = ifs.GetNCoord(); // See float attributes note.
 
     if (primitives[0].attributes.position[0]->count != size_coord)
-        throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (", to_string(size_coord),
-                                ") not equal to uncompressed (", to_string(primitives[0].attributes.position[0]->count), ").");
+        throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (", ai_to_string(size_coord),
+                ") not equal to uncompressed (", ai_to_string(primitives[0].attributes.position[0]->count), ").");
 
     size_coord *= 3 * sizeof(float);
     // Normals
     size_t size_normal = ifs.GetNNormal(); // See float attributes note.
 
     if (primitives[0].attributes.normal[0]->count != size_normal)
-        throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (", to_string(size_normal),
-                                ") not equal to uncompressed (", to_string(primitives[0].attributes.normal[0]->count), ").");
+        throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (", ai_to_string(size_normal),
+                ") not equal to uncompressed (", ai_to_string(primitives[0].attributes.normal[0]->count), ").");
 
     size_normal *= 3 * sizeof(float);
     // Additional attributes.
@@ -965,8 +965,8 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
                 // Check situation when encoded data contain texture coordinates but primitive not.
                 if (idx_texcoord < primitives[0].attributes.texcoord.size()) {
                     if (primitives[0].attributes.texcoord[idx]->count != tval)
-                        throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (", to_string(tval),
-                                                ") not equal to uncompressed (", to_string(primitives[0].attributes.texcoord[idx]->count), ").");
+                        throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (", ai_to_string(tval),
+                                ") not equal to uncompressed (", ai_to_string(primitives[0].attributes.texcoord[idx]->count), ").");
 
                     idx_texcoord++;
                 } else {
@@ -975,7 +975,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
 
                 break;
             default:
-                throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: ", to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
+                throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: ", ai_to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
         }
 
         tval *= ifs.GetFloatAttributeDim(static_cast<unsigned long>(idx)) * sizeof(o3dgc::Real); // After checking count of objects we can get size of array.
@@ -994,7 +994,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
                 break;
 
             default:
-                throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: ", to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
+                throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: ", ai_to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
         }
 
         tval *= ifs.GetIntAttributeDim(static_cast<unsigned long>(idx)) * sizeof(long); // See float attributes note.
@@ -1029,7 +1029,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
 
                 break;
             default:
-                throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: ", to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
+                throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: ", ai_to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
         }
     }
 
@@ -1043,7 +1043,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
 
             // ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint)));
             default:
-                throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: ", to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
+                throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: ", ai_to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
         }
     }
 
@@ -1254,7 +1254,7 @@ inline void Asset::ReadBinaryHeader(IOStream &stream) {
     }
 
     AI_SWAP4(header.version);
-    asset.version = to_string(header.version);
+    asset.version = ai_to_string(header.version);
     if (header.version != 1) {
         throw DeadlyImportError("GLTF: Unsupported binary glTF version");
     }

+ 1 - 1
code/AssetLib/glTF/glTFExporter.cpp

@@ -1003,7 +1003,7 @@ void glTFExporter::ExportAnimations()
 
             // It appears that assimp stores this type of animation as multiple animations.
             // where each aiNodeAnim in mChannels animates a specific node.
-            std::string name = nameAnim + "_" + to_string(channelIndex);
+            std::string name = nameAnim + "_" + ai_to_string(channelIndex);
             name = mAsset->FindUniqueID(name, "animation");
             Ref<Animation> animRef = mAsset->animations.Create(name);
 

+ 1 - 1
code/AssetLib/glTF/glTFImporter.cpp

@@ -234,7 +234,7 @@ void glTFImporter::ImportMeshes(glTF::Asset &r) {
                     buf->EncodedRegion_SetCurrent(mesh.id);
                 } else
                 {
-                    throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"", to_string(cur_ext->Type),
+                    throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"", ai_to_string(cur_ext->Type),
                                             "\"), only Open3DGC is supported.");
                 }
             }

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

@@ -197,7 +197,7 @@ inline unsigned int ComponentTypeSize(ComponentType t) {
     case ComponentType_UNSIGNED_BYTE:
         return 1;
     default:
-        throw DeadlyImportError("GLTF: Unsupported Component Type ", to_string(t));
+        throw DeadlyImportError("GLTF: Unsupported Component Type ", ai_to_string(t));
     }
 }
 

+ 6 - 6
code/AssetLib/glTF2/glTF2Asset.inl

@@ -446,7 +446,7 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
     // Unique ptr prevents memory leak in case of Read throws an exception
     auto inst = std::unique_ptr<T>(new T());
     // Try to make this human readable so it can be used in error messages.
-    inst->id = std::string(mDictId) + "[" + to_string(i) + "]";
+    inst->id = std::string(mDictId) + "[" + ai_to_string(i) + "]";
     inst->oIndex = i;
     ReadMember(obj, "name", inst->name);
     inst->Read(obj, mAsset);
@@ -538,13 +538,13 @@ inline void Buffer::Read(Value &obj, Asset &r) {
             this->mData.reset(data, std::default_delete<uint8_t[]>());
 
             if (statedLength > 0 && this->byteLength != statedLength) {
-                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
-                        " bytes, but found ", to_string(dataURI.dataLength));
+                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength),
+                        " bytes, but found ", ai_to_string(dataURI.dataLength));
             }
         } else { // assume raw data
             if (statedLength != dataURI.dataLength) {
-                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
-                        " bytes, but found ", to_string(dataURI.dataLength));
+                throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", ai_to_string(statedLength),
+                        " bytes, but found ", ai_to_string(dataURI.dataLength));
             }
 
             this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>());
@@ -1800,7 +1800,7 @@ inline void Asset::ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneDa
     }
 
     AI_SWAP4(header.version);
-    asset.version = to_string(header.version);
+    asset.version = ai_to_string(header.version);
     if (header.version != 2) {
         throw DeadlyImportError("GLTF: Unsupported binary glTF version");
     }

+ 2 - 2
code/AssetLib/glTF2/glTF2Exporter.cpp

@@ -602,7 +602,7 @@ void glTF2Exporter::ExportMaterials()
     for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
         const aiMaterial* mat = mScene->mMaterials[i];
 
-        std::string id = "material_" + to_string(i);
+        std::string id = "material_" + ai_to_string(i);
 
         Ref<Material> m = mAsset->materials.Create(id);
 
@@ -1393,7 +1393,7 @@ void glTF2Exporter::ExportAnimations()
         for (unsigned int channelIndex = 0; channelIndex < anim->mNumChannels; ++channelIndex) {
             const aiNodeAnim* nodeChannel = anim->mChannels[channelIndex];
 
-            std::string name = nameAnim + "_" + to_string(channelIndex);
+            std::string name = nameAnim + "_" + ai_to_string(channelIndex);
             name = mAsset->FindUniqueID(name, "animation");
 
             Ref<Node> animNode = mAsset->nodes.Get(nodeChannel->mNodeName.C_Str());

+ 1 - 1
code/Common/BaseImporter.cpp

@@ -276,7 +276,7 @@ std::string BaseImporter::GetExtension(const std::string &file) {
 
     // thanks to Andy Maloney for the hint
     std::string ret = file.substr(pos + 1);
-    std::transform(ret.begin(), ret.end(), ret.begin(), ToLower<char>);
+    ret = ai_str_tolower(ret);
 
     return ret;
 }

+ 2 - 3
code/Common/Importer.cpp

@@ -975,15 +975,14 @@ size_t Importer::GetImporterIndex (const char* szExtension) const {
 
     ASSIMP_BEGIN_EXCEPTION_REGION();
 
-    // skip over wildcard and dot characters at string head --
+    // skip over wild-card and dot characters at string head --
     for ( ; *szExtension == '*' || *szExtension == '.'; ++szExtension );
 
     std::string ext(szExtension);
     if (ext.empty()) {
         return static_cast<size_t>(-1);
     }
-    std::transform( ext.begin(), ext.end(), ext.begin(), ToLower<char> );
-
+    ext = ai_str_tolower(ext);
     std::set<std::string> str;
     for (std::vector<BaseImporter*>::const_iterator i =  pimpl->mImporter.begin();i != pimpl->mImporter.end();++i)  {
         str.clear();

+ 3 - 3
code/PostProcessing/ComputeUVMappingProcess.cpp

@@ -122,7 +122,7 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
         const aiFace& face = mesh->mFaces[fidx];
         if (face.mNumIndices < 3) continue; // triangles and polygons only, please
 
-        unsigned int small = face.mNumIndices, large = small;
+        unsigned int smallV = face.mNumIndices, large = smallV;
         bool zero = false, one = false, round_to_zero = false;
 
         // Check whether this face lies on a UV seam. We can just guess,
@@ -133,7 +133,7 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
         {
             if (out[face.mIndices[n]].x < LOWER_LIMIT)
             {
-                small = n;
+                smallV = n;
 
                 // If we have a U value very close to 0 we can't
                 // round the others to 0, too.
@@ -151,7 +151,7 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
                     one = true;
             }
         }
-        if (small != face.mNumIndices && large != face.mNumIndices)
+        if (smallV != face.mNumIndices && large != face.mNumIndices)
         {
             for (unsigned int n = 0; n < face.mNumIndices;++n)
             {

+ 1 - 1
code/PostProcessing/EmbedTexturesProcess.cpp

@@ -137,7 +137,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
     pTexture->pcData = imageContent;
 
     auto extension = path.substr(path.find_last_of('.') + 1u);
-    std::transform(extension.begin(), extension.end(), extension.begin(), ToLower<char> );
+    extension = ai_str_tolower(extension);
     if (extension == "jpeg") {
         extension = "jpg";
     }

+ 4 - 0
contrib/unzip/crypt.c

@@ -21,6 +21,10 @@
    NOCRYPT and NOUNCRYPT.
 */
 
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
+    #define MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS 0
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>

+ 8 - 0
include/assimp/Exceptional.h

@@ -75,6 +75,10 @@ public:
     template<typename... T>
     explicit DeadlyImportError(T&&... args) :
             DeadlyErrorBase(Assimp::Formatter::format(), std::forward<T>(args)...) {}
+
+#if defined(_MSC_VER) && defined(__clang__)
+    DeadlyImportError(DeadlyImportError& other) = delete;
+#endif
 };
 
 class ASSIMP_API DeadlyExportError : public DeadlyErrorBase {
@@ -83,6 +87,10 @@ public:
     template<typename... T>
     explicit DeadlyExportError(T&&... args) :
             DeadlyErrorBase(Assimp::Formatter::format(), std::forward<T>(args)...) {}
+
+#if defined(_MSC_VER) && defined(__clang__)
+    DeadlyExportError(DeadlyExportError& other) = delete;
+#endif
 };
 
 #ifdef _MSC_VER

+ 2 - 11
include/assimp/ParsingUtils.h

@@ -53,7 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/StringComparison.h>
 #include <assimp/StringUtils.h>
 #include <assimp/defs.h>
+
 #include <vector>
+#include <algorithm>
 
 namespace Assimp {
 
@@ -68,17 +70,6 @@ namespace Assimp {
 
 static const unsigned int BufferSize = 4096;
 
-// ---------------------------------------------------------------------------------
-template <class char_t>
-AI_FORCE_INLINE char_t ToLower(char_t in) {
-    return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in + 0x20) : in;
-}
-
-// ---------------------------------------------------------------------------------
-template <class char_t>
-AI_FORCE_INLINE char_t ToUpper(char_t in) {
-    return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in - 0x20) : in;
-}
 
 // ---------------------------------------------------------------------------------
 template <class char_t>

+ 10 - 15
include/assimp/StringComparison.h

@@ -61,8 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/ai_assert.h>
 #include <assimp/defs.h>
 
-#include <stdint.h>
-#include <string.h>
+#include <cstdint>
+#include <cstring>
 #include <string>
 
 namespace Assimp {
@@ -78,8 +78,7 @@ namespace Assimp {
  * @param number Number to be written
  * @return Length of the output string, excluding the '\0'
  */
-AI_FORCE_INLINE
-unsigned int ASSIMP_itoa10(char *out, unsigned int max, int32_t number) {
+inline unsigned int ASSIMP_itoa10(char *out, unsigned int max, int32_t number) {
     ai_assert(nullptr != out);
 
     // write the unary minus to indicate we have a negative number
@@ -97,7 +96,7 @@ unsigned int ASSIMP_itoa10(char *out, unsigned int max, int32_t number) {
 
         const unsigned int digit = number / cur;
         if (mustPrint || digit > 0 || 1 == cur) {
-            // print all future zeroe's from now
+            // print all future zero's from now
             mustPrint = true;
 
             *out++ = '0' + static_cast<char>(digit);
@@ -122,7 +121,7 @@ unsigned int ASSIMP_itoa10(char *out, unsigned int max, int32_t number) {
  *  size of the array automatically.
  */
 template <size_t length>
-AI_FORCE_INLINE unsigned int ASSIMP_itoa10(char (&out)[length], int32_t number) {
+inline unsigned int ASSIMP_itoa10(char (&out)[length], int32_t number) {
     return ASSIMP_itoa10(out, length, number);
 }
 
@@ -137,8 +136,7 @@ AI_FORCE_INLINE unsigned int ASSIMP_itoa10(char (&out)[length], int32_t number)
  *  @param s2 Second input string
  *  @return 0 if the given strings are identical
  */
-AI_FORCE_INLINE
-int ASSIMP_stricmp(const char *s1, const char *s2) {
+inline int ASSIMP_stricmp(const char *s1, const char *s2) {
     ai_assert(nullptr != s1);
     ai_assert(nullptr != s2);
 
@@ -162,8 +160,7 @@ int ASSIMP_stricmp(const char *s1, const char *s2) {
  *  @param b Second string
  *  @return 0 if a == b
  */
-AI_FORCE_INLINE
-int ASSIMP_stricmp(const std::string &a, const std::string &b) {
+inline int ASSIMP_stricmp(const std::string &a, const std::string &b) {
     int i = (int)b.length() - (int)a.length();
     return (i ? i : ASSIMP_stricmp(a.c_str(), b.c_str()));
 }
@@ -177,11 +174,10 @@ int ASSIMP_stricmp(const std::string &a, const std::string &b) {
  *
  *  @param s1 First input string
  *  @param s2 Second input string
- *  @param n Macimum number of characters to compare
+ *  @param n Maximum number of characters to compare
  *  @return 0 if the given strings are identical
  */
-AI_FORCE_INLINE
-int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) {
+inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) {
     ai_assert(nullptr != s1);
     ai_assert(nullptr != s2);
     if (!n) {
@@ -214,8 +210,7 @@ int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) {
  *
  * todo: move somewhere where it fits better in than here
  */
-AI_FORCE_INLINE
-unsigned int integer_pow(unsigned int base, unsigned int power) {
+inline unsigned int integer_pow(unsigned int base, unsigned int power) {
     unsigned int res = 1;
     for (unsigned int i = 0; i < power; ++i) {
         res *= base;

+ 80 - 23
include/assimp/StringUtils.h

@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/defs.h>
 
-#include <stdarg.h>
+#include <cstdarg>
 #include <algorithm>
 #include <cctype>
 #include <cstdlib>
@@ -62,17 +62,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_SIZEFMT "%zu"
 #endif
 
+// ---------------------------------------------------------------------------------
 ///	@fn		ai_snprintf
-///	@brief	The portable version of the function snprintf ( C99 standard ), which works on visual studio compilers 2013 and earlier.
+///	@brief	The portable version of the function snprintf ( C99 standard ), which
+///         works on visual studio compilers 2013 and earlier.
 ///	@param	outBuf		The buffer to write in
 ///	@param	size		The buffer size
 ///	@param	format		The format string
 ///	@param	ap			The additional arguments.
-///	@return	The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned.
+///	@return	The number of written characters if the buffer size was big enough.
+///         If an encoding error occurs, a negative number is returned.
+// ---------------------------------------------------------------------------------
 #if defined(_MSC_VER) && _MSC_VER < 1900
 
-AI_FORCE_INLINE
-int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
+inline int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
     int count(-1);
     if (0 != size) {
         count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
@@ -84,8 +87,7 @@ int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
     return count;
 }
 
-AI_FORCE_INLINE
-int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
+inline int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
     int count;
     va_list ap;
 
@@ -102,23 +104,28 @@ int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
 #define ai_snprintf snprintf
 #endif
 
+// ---------------------------------------------------------------------------------
 ///	@fn		to_string
-///	@brief	The portable version of to_string ( some gcc-versions on embedded devices are not supporting this).
+///	@brief	The portable version of to_string ( some gcc-versions on embedded
+///         devices are not supporting this).
 ///	@param	value   The value to write into the std::string.
 ///	@return	The value as a std::string
+// ---------------------------------------------------------------------------------
 template <typename T>
-AI_FORCE_INLINE std::string to_string(T value) {
+AI_FORCE_INLINE std::string ai_to_string(T value) {
     std::ostringstream os;
     os << value;
 
     return os.str();
 }
 
+// ---------------------------------------------------------------------------------
 ///	@fn		ai_strtof
 ///	@brief	The portable version of strtof.
 ///	@param	begin   The first character of the string.
 /// @param  end     The last character
-///	@return	The float value, 0.0f in cas of an error.
+///	@return	The float value, 0.0f in case of an error.
+// ---------------------------------------------------------------------------------
 AI_FORCE_INLINE
 float ai_strtof(const char *begin, const char *end) {
     if (nullptr == begin) {
@@ -136,12 +143,14 @@ float ai_strtof(const char *begin, const char *end) {
     return val;
 }
 
+// ---------------------------------------------------------------------------------
 ///	@fn		DecimalToHexa
 ///	@brief	The portable to convert a decimal value into a hexadecimal string.
 ///	@param	toConvert   Value to convert
 ///	@return	The hexadecimal string, is empty in case of an error.
+// ---------------------------------------------------------------------------------
 template <class T>
-AI_FORCE_INLINE std::string DecimalToHexa(T toConvert) {
+AI_FORCE_INLINE std::string ai_decimal_to_hexa(T toConvert) {
     std::string result;
     std::stringstream ss;
     ss << std::hex << toConvert;
@@ -154,6 +163,7 @@ AI_FORCE_INLINE std::string DecimalToHexa(T toConvert) {
     return result;
 }
 
+// ---------------------------------------------------------------------------------
 ///	@brief	translate RGBA to String
 ///	@param	r   aiColor.r
 ///	@param	g   aiColor.g
@@ -161,7 +171,8 @@ AI_FORCE_INLINE std::string DecimalToHexa(T toConvert) {
 ///	@param	a   aiColor.a
 ///	@param	with_head   #
 ///	@return	The hexadecimal string, is empty in case of an error.
-AI_FORCE_INLINE std::string Rgba2Hex(int r, int g, int b, int a, bool with_head) {
+// ---------------------------------------------------------------------------------
+AI_FORCE_INLINE std::string ai_rgba2hex(int r, int g, int b, int a, bool with_head) {
     std::stringstream ss;
     if (with_head) {
         ss << "#";
@@ -171,25 +182,71 @@ AI_FORCE_INLINE std::string Rgba2Hex(int r, int g, int b, int a, bool with_head)
     return ss.str();
 }
 
-// trim from start (in place)
-AI_FORCE_INLINE void ltrim(std::string &s) {
+// ---------------------------------------------------------------------------------
+/// @brief   Performs a trim from start (in place)
+/// @param  s   string to trim.
+AI_FORCE_INLINE void ai_trim_left(std::string &s) {
     s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
         return !std::isspace(ch);
     }));
 }
 
-// trim from end (in place)
-AI_FORCE_INLINE void rtrim(std::string &s) {
+// ---------------------------------------------------------------------------------
+/// @brief  Performs a trim from end (in place).
+/// @param  s   string to trim.
+// ---------------------------------------------------------------------------------
+// ---------------------------------------------------------------------------------
+AI_FORCE_INLINE void ai_trim_right(std::string &s) {
     s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
         return !std::isspace(ch);
-    }).base(),
-            s.end());
+    }).base(), s.end());
+}
+
+// ---------------------------------------------------------------------------------
+/// @brief  Performs a trim from both ends (in place).
+/// @param  s   string to trim.
+// ---------------------------------------------------------------------------------
+AI_FORCE_INLINE std::string ai_trim(std::string &s) {
+    std::string out(s);
+    ai_trim_left(out);
+    ai_trim_right(out);
+
+    return out;
+}
+
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE char_t ai_tolower(char_t in) {
+    return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in + 0x20) : in;
+}
+
+// ---------------------------------------------------------------------------------
+/// @brief  Performs a ToLower-operation and return the lower-case string.
+/// @param  in  The incoming string.
+/// @return The string as lowercase.
+// ---------------------------------------------------------------------------------
+AI_FORCE_INLINE std::string ai_str_tolower(const std::string &in) {
+    std::string out(in);
+    ai_trim_left(out);
+    ai_trim_right(out);
+    std::transform(out.begin(), out.end(), out.begin(), [](unsigned char c) { return ai_tolower(c); });
+    return out;
 }
 
-// trim from both ends (in place)
-AI_FORCE_INLINE void trim(std::string &s) {
-    ltrim(s);
-    rtrim(s);
+// ---------------------------------------------------------------------------------
+template <class char_t>
+AI_FORCE_INLINE char_t ai_toupper(char_t in) {
+    return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in - 0x20) : in;
 }
 
-#endif // INCLUDED_AI_STRINGUTILS_H
+// ---------------------------------------------------------------------------------
+/// @brief  Performs a ToLower-operation and return the upper-case string.
+/// @param  in  The incoming string.
+/// @return The string as uppercase.
+AI_FORCE_INLINE std::string ai_str_toupper(const std::string &in) {
+    std::string out(in);
+    std::transform(out.begin(), out.end(), out.begin(), [](char c) { return ai_toupper(c); });
+    return out;
+}
+
+#endif

+ 8 - 0
include/assimp/importerdesc.h

@@ -52,6 +52,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/types.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /** Mixed set of flags for #aiImporterDesc, indicating some features
   *  common to many importers*/
 enum aiImporterFlags {
@@ -143,4 +147,8 @@ Will return a nullptr if no assigned importer desc. was found for the given exte
 */
 ASSIMP_API const C_STRUCT aiImporterDesc *aiGetImporterDesc(const char *extension);
 
+#ifdef __cplusplus
+} // end of extern "C"
+#endif
+
 #endif // AI_IMPORTER_DESC_H_INC

+ 1 - 1
include/assimp/metadata.h

@@ -351,7 +351,7 @@ struct aiMetadata {
             *static_cast<T *>(mValues[index].mData) = value;
         } else {
             if (nullptr != mValues[index].mData) {
-                delete mValues[index].mData;
+                delete static_cast<T *>(mValues[index].mData);
                 mValues[index].mData = nullptr;
             }
             mValues[index].mData = new T(value);

+ 2 - 2
test/unit/utStringUtils.cpp

@@ -45,10 +45,10 @@ class utStringUtils : public ::testing::Test {
 };
 
 TEST_F( utStringUtils, to_string_Test ) {
-    std::string res = to_string( 1 );
+    std::string res = ai_to_string( 1 );
     EXPECT_EQ( res, "1" );
 
-    res = to_string( 1.0f );
+    res = ai_to_string( 1.0f );
     EXPECT_EQ( res, "1" );
 }
 

+ 2 - 1
tools/assimp_cmd/Export.cpp

@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "Main.h"
 #include <assimp/ParsingUtils.h>
+#include <assimp/StringUtils.h>
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 
@@ -107,7 +108,7 @@ int Assimp_Export(const char *const *params, unsigned int num) {
         }
     }
 
-    std::transform(outf.begin(), outf.end(), outf.begin(), Assimp::ToLower<char>);
+    std::transform(outf.begin(), outf.end(), outf.begin(), ai_tolower<char>);
 
     // convert the output format to a format id
     size_t outfi = GetMatchingFormat(outf);

+ 1 - 1
tools/assimp_cmd/ImageExtractor.cpp

@@ -266,7 +266,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
 #endif
     }
 
-    std::transform(extension.begin(), extension.end(), extension.begin(), Assimp::ToLower<char>);
+    std::transform(extension.begin(), extension.end(), extension.begin(), ai_tolower<char>);
 
     if (out[0] == '-') {
         // take file name from input file