diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 1c533aa80..db152b813 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -54,7 +54,7 @@ jobs: - name: Cache DX SDK id: dxcache if: contains(matrix.name, 'windows') - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: '${{ github.workspace }}/DX_SDK' key: ${{ runner.os }}-DX_SDK diff --git a/.github/workflows/inno_setup b/.github/workflows/inno_setup new file mode 100644 index 000000000..0bfef0cd3 --- /dev/null +++ b/.github/workflows/inno_setup @@ -0,0 +1,51 @@ +name: Build Windows Installer +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +jobs: + build: + name: Build the Inno Setup Installer + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: lukka/get-cmake@latest + - uses: ilammy/msvc-dev-cmd@v1 + + + - name: Cache DX SDK + id: dxcache + uses: actions/cache@v4 + with: + path: '${{ github.workspace }}/DX_SDK' + key: ${{ runner.os }}-DX_SDK + restore-keys: | + ${{ runner.os }}-DX_SDK + + - name: Download DXSetup + run: | + curl -s -o DXSDK_Jun10.exe --location https://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe + cmd.exe /c start /wait .\DXSDK_Jun10.exe /U /O /F /S /P "${{ github.workspace }}\DX_SDK" + + - name: Set Windows specific CMake arguments + id: windows_extra_cmake_args + run: echo "::set-output name=args::-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1 -DASSIMP_BUILD_ZLIB=1" + + - name: configure and build + uses: lukka/run-cmake@v3 + env: + DXSDK_DIR: '${{ github.workspace }}/DX_SDK' + + with: + cmakeListsOrSettingsJson: CMakeListsTxtAdvanced + cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release ${{ steps.windows_extra_cmake_args.outputs.args }} ${{ steps.hunter_extra_cmake_args.outputs.args }}' + buildWithCMakeArgs: '--parallel 24 -v' + buildDirectory: '${{ github.workspace }}/build/' + + - name: Compile .ISS to .EXE Installer + uses: Minionguyjpro/Inno-Setup-Action@v1.2.2 + with: + path: packaging/windows-innosetup/script_x64.iss + options: /O+ diff --git a/CMakeLists.txt b/CMakeLists.txt index 868282ef2..718a251e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- -# Copyright (c) 2006-2023, assimp team +# Copyright (c) 2006-2024, assimp team # # All rights reserved. # @@ -38,9 +38,9 @@ SET(CMAKE_POLICY_DEFAULT_CMP0012 NEW) SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW) SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW) -CMAKE_MINIMUM_REQUIRED( VERSION 3.10 ) +CMAKE_MINIMUM_REQUIRED( VERSION 3.22 ) -# Disabled importers: m3d for 5.1 +# Disabled importers: m3d for 5.1 or later ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER) # Toggles the use of the hunter package manager @@ -49,13 +49,13 @@ option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF) IF(ASSIMP_HUNTER_ENABLED) include("cmake-modules/HunterGate.cmake") HunterGate( - URL "https://github.com/cpp-pm/hunter/archive/v0.24.18.tar.gz" - SHA1 "1292e4d661e1770d6d6ca08c12c07cf34a0bf718" + URL "https://github.com/cpp-pm/hunter/archive/v0.25.5.tar.gz" + SHA1 "a20151e4c0740ee7d0f9994476856d813cdead29" ) add_definitions(-DASSIMP_USE_HUNTER) ENDIF() -PROJECT(Assimp VERSION 5.3.0) +PROJECT(Assimp VERSION 5.4.1) # All supported options ############################################### @@ -131,18 +131,18 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH IF (WIN32) OPTION( ASSIMP_BUILD_ZLIB - "Build your own zlib" + "Build your zlib" ON ) ELSE() OPTION( ASSIMP_BUILD_ZLIB - "Build your own zlib" + "Build your zlib" OFF ) ENDIF() IF (WIN32) - # Use subset of Windows.h + # Use a subset of Windows.h ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN ) IF(MSVC) @@ -150,16 +150,16 @@ IF (WIN32) "Install MSVC debug files." ON ) IF(NOT (MSVC_VERSION LESS 1900)) - # Multibyte character set is deprecated since at least MSVC2015 (possibly earlier) + # Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier) ADD_DEFINITIONS( -DUNICODE -D_UNICODE ) ENDIF() - # Link statically against c/c++ lib to avoid missing redistriburable such as + # Link statically against c/c++ lib to avoid missing redistributable such as # "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users # a choice to opt for the shared runtime if they want. option(USE_STATIC_CRT "Link against the static runtime libraries." OFF) - # The CMAKE_CXX_FLAGS vars can be overriden by some Visual Studio generators, so we use an alternative + # The CMAKE_CXX_FLAGS vars can be overridden by some Visual Studio generators, so we use an alternative # global method here: if (${USE_STATIC_CRT}) add_compile_options( @@ -249,9 +249,9 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") IF( UNIX ) # Use GNUInstallDirs for Unix predefined directories INCLUDE(GNUInstallDirs) - # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux + # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit Linux IF(NOT ${OPERATING_SYSTEM} MATCHES "Android") - IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux + IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit Linux ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) ENDIF() ENDIF() @@ -289,7 +289,7 @@ ELSEIF(MSVC) IF(MSVC12) ADD_COMPILE_OPTIONS(/wd4351) ENDIF() - # supress warning for double to float conversion if Double precission is activated + # supress warning for double to float conversion if Double precision is activated ADD_COMPILE_OPTIONS(/wd4244) SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") @@ -452,18 +452,20 @@ configure_package_config_file( INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" ) -install( - FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" - DESTINATION "${CONFIG_INSTALL_DIR}" - COMPONENT ${LIBASSIMP-DEV_COMPONENT} -) +if(ASSIMP_INSTALL) + install( + FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" + DESTINATION "${CONFIG_INSTALL_DIR}" + COMPONENT ${LIBASSIMP-DEV_COMPONENT} + ) -install( - EXPORT "${TARGETS_EXPORT_NAME}" - NAMESPACE "${NAMESPACE}" - DESTINATION "${CONFIG_INSTALL_DIR}" - COMPONENT ${LIBASSIMP-DEV_COMPONENT} -) + install( + EXPORT "${TARGETS_EXPORT_NAME}" + NAMESPACE "${NAMESPACE}" + DESTINATION "${CONFIG_INSTALL_DIR}" + COMPONENT ${LIBASSIMP-DEV_COMPONENT} + ) +endif() IF( ASSIMP_BUILD_DOCS ) ADD_SUBDIRECTORY(doc) @@ -481,7 +483,7 @@ IF(ASSIMP_HUNTER_ENABLED) set(ASSIMP_BUILD_MINIZIP TRUE) ELSE() # If the zlib is already found outside, add an export in case assimpTargets can't find it. - IF( ZLIB_FOUND ) + IF( ZLIB_FOUND AND ASSIMP_INSTALL) INSTALL( TARGETS zlib zlibstatic EXPORT "${TARGETS_EXPORT_NAME}") ENDIF() @@ -563,9 +565,9 @@ SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL ) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) - IF ( MSVC ) - SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes") + SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes") + IF (WIN32) # pick the correct prebuilt library IF(MSVC143) SET(C4D_LIB_POSTFIX "_2022") @@ -583,7 +585,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) SET(C4D_LIB_POSTFIX "_2010") ELSE() MESSAGE( FATAL_ERROR - "C4D is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3" + "C4D for Windows is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3" ) ENDIF() @@ -601,15 +603,30 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because # it can be used to communicate with a running Cinema 4D instance SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib) + ELSEIF (APPLE) + SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/osx") + + SET(C4D_DEBUG_LIBRARIES + "${C4D_LIB_BASE_PATH}/debug/libcinewarelib.a" + "${C4D_LIB_BASE_PATH}/debug/libjpeglib.a" + ) + SET(C4D_RELEASE_LIBRARIES + "${C4D_LIB_BASE_PATH}/release/libcinewarelib.a" + "${C4D_LIB_BASE_PATH}/release/libjpeglib.a" + ) ELSE () MESSAGE( FATAL_ERROR - "C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware" + "C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware" ) ENDIF () ELSE () ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) ENDIF () +if(ASSIMP_BUILD_DRACO_STATIC) + set(ASSIMP_BUILD_DRACO ON) +endif() + # Draco requires cmake 3.12 IF (DEFINED CMAKE_VERSION AND "${CMAKE_VERSION}" VERSION_LESS "3.12") message(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled") @@ -645,22 +662,29 @@ ELSE() "-Wno-sign-compare" "-Wno-unused-local-typedefs" ) - # Draco 1.4.1 does not explicitly export any symbols under GCC/clang - list(APPEND DRACO_CXX_FLAGS - "-fvisibility=default" - ) + + if(NOT ASSIMP_BUILD_DRACO_STATIC) + # Draco 1.4.1 does not explicitly export any symbols under GCC/clang + list(APPEND DRACO_CXX_FLAGS + "-fvisibility=default" + ) + endif() ENDIF() # Don't build or install all of Draco by default ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL ) + if(ASSIMP_BUILD_DRACO_STATIC) + set_property(DIRECTORY "contrib/draco" PROPERTY BUILD_SHARED_LIBS OFF) + endif() + if(MSVC OR WIN32) set(draco_LIBRARIES "draco") else() - if(BUILD_SHARED_LIBS) - set(draco_LIBRARIES "draco_shared") - else() + if(ASSIMP_BUILD_DRACO_STATIC) set(draco_LIBRARIES "draco_static") + else() + set(draco_LIBRARIES "draco_shared") endif() endif() @@ -683,15 +707,17 @@ ELSE() set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src") # This is probably wrong - INSTALL( TARGETS ${draco_LIBRARIES} - EXPORT "${TARGETS_EXPORT_NAME}" - LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} - FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - COMPONENT ${LIBASSIMP_COMPONENT} - INCLUDES DESTINATION include - ) + if (ASSIMP_INSTALL) + INSTALL( TARGETS ${draco_LIBRARIES} + EXPORT "${TARGETS_EXPORT_NAME}" + LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} + FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + COMPONENT ${LIBASSIMP_COMPONENT} + INCLUDES DESTINATION include + ) + endif() ENDIF() ENDIF() ENDIF() @@ -735,8 +761,8 @@ IF ( ASSIMP_INSTALL ) ENDIF() CONFIGURE_FILE( - ${CMAKE_CURRENT_LIST_DIR}/revision.h.in - ${CMAKE_CURRENT_BINARY_DIR}/revision.h + ${CMAKE_CURRENT_LIST_DIR}/include/assimp/revision.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/revision.h ) CONFIGURE_FILE( diff --git a/cmake-modules/HunterGate.cmake b/cmake-modules/HunterGate.cmake index 6d9cc2401..fe02e3614 100644 --- a/cmake-modules/HunterGate.cmake +++ b/cmake-modules/HunterGate.cmake @@ -22,38 +22,9 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# This is a gate file to Hunter package manager. -# Include this file using `include` command and add package you need, example: -# -# cmake_minimum_required(VERSION 3.2) -# -# include("cmake/HunterGate.cmake") -# HunterGate( -# URL "https://github.com/path/to/hunter/archive.tar.gz" -# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d" -# ) -# -# project(MyProject) -# -# hunter_add_package(Foo) -# hunter_add_package(Boo COMPONENTS Bar Baz) -# -# Projects: -# * https://github.com/hunter-packages/gate/ -# * https://github.com/ruslo/hunter option(HUNTER_ENABLED "Enable Hunter package manager support" ON) -if(HUNTER_ENABLED) - if(CMAKE_VERSION VERSION_LESS "3.2") - message( - FATAL_ERROR - "At least CMake version 3.2 required for Hunter dependency management." - " Update CMake or set HUNTER_ENABLED to OFF." - ) - endif() -endif() - include(CMakeParseArguments) # cmake_parse_arguments option(HUNTER_STATUS_PRINT "Print working status" ON) diff --git a/code/AssetLib/3DS/3DSConverter.cpp b/code/AssetLib/3DS/3DSConverter.cpp index 6d3f09cb7..7d1c24cd6 100644 --- a/code/AssetLib/3DS/3DSConverter.cpp +++ b/code/AssetLib/3DS/3DSConverter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -709,7 +709,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) { pcNode->mNumMeshes = 1; // Build a name for the node - pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u", i); + pcNode->mName.length = ai_snprintf(pcNode->mName.data, AI_MAXLEN, "3DSMesh_%u", i); } // Build dummy nodes for all cameras diff --git a/code/AssetLib/3DS/3DSExporter.cpp b/code/AssetLib/3DS/3DSExporter.cpp index 1b335a272..8477ed09f 100644 --- a/code/AssetLib/3DS/3DSExporter.cpp +++ b/code/AssetLib/3DS/3DSExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3DS/3DSExporter.h b/code/AssetLib/3DS/3DSExporter.h index 66e91e10d..9e3e42911 100644 --- a/code/AssetLib/3DS/3DSExporter.h +++ b/code/AssetLib/3DS/3DSExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h index 2279d105c..8f85f2e4d 100644 --- a/code/AssetLib/3DS/3DSHelper.h +++ b/code/AssetLib/3DS/3DSHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp index a406ea1d2..3317017be 100644 --- a/code/AssetLib/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3DS/3DSLoader.h b/code/AssetLib/3DS/3DSLoader.h index c579507e0..1d6953e29 100644 --- a/code/AssetLib/3DS/3DSLoader.h +++ b/code/AssetLib/3DS/3DSLoader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/3MFTypes.h b/code/AssetLib/3MF/3MFTypes.h index 8207b568b..57d2b281a 100644 --- a/code/AssetLib/3MF/3MFTypes.h +++ b/code/AssetLib/3MF/3MFTypes.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -57,6 +57,7 @@ enum class ResourceType { RT_BaseMaterials, RT_EmbeddedTexture2D, RT_Texture2DGroup, + RT_ColorGroup, RT_Unknown }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...) @@ -117,6 +118,21 @@ public: } }; +class ColorGroup : public Resource { +public: + std::vector mColors; + ColorGroup(int id) : + Resource(id){ + // empty + } + + ~ColorGroup() override = default; + + ResourceType getType() const override { + return ResourceType::RT_ColorGroup; + } +}; + class BaseMaterials : public Resource { public: std::vector mMaterialIndex; diff --git a/code/AssetLib/3MF/3MFXmlTags.h b/code/AssetLib/3MF/3MFXmlTags.h index 333d169aa..aea66667b 100644 --- a/code/AssetLib/3MF/3MFXmlTags.h +++ b/code/AssetLib/3MF/3MFXmlTags.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -98,6 +98,11 @@ namespace XmlTag { const char *const texture_cuurd_u = "u"; const char *const texture_cuurd_v = "v"; + // vertex color definitions + const char *const colorgroup = "m:colorgroup"; + const char *const color_item = "m:color"; + const char *const color_vaule = "color"; + // Meta info tags const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; diff --git a/code/AssetLib/3MF/D3MFExporter.cpp b/code/AssetLib/3MF/D3MFExporter.cpp index 4ba3bbf24..6caa4c84e 100644 --- a/code/AssetLib/3MF/D3MFExporter.cpp +++ b/code/AssetLib/3MF/D3MFExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/D3MFExporter.h b/code/AssetLib/3MF/D3MFExporter.h index 680d54f91..6be0c32ca 100644 --- a/code/AssetLib/3MF/D3MFExporter.h +++ b/code/AssetLib/3MF/D3MFExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/D3MFImporter.cpp b/code/AssetLib/3MF/D3MFImporter.cpp index 9a5081db9..987cdd492 100644 --- a/code/AssetLib/3MF/D3MFImporter.cpp +++ b/code/AssetLib/3MF/D3MFImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/D3MFImporter.h b/code/AssetLib/3MF/D3MFImporter.h index 9ae68acb0..82a1546cd 100644 --- a/code/AssetLib/3MF/D3MFImporter.h +++ b/code/AssetLib/3MF/D3MFImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index e772d8b7e..be0615904 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -119,9 +119,9 @@ public: static bool IsEmbeddedTexture( const std::string &filename ) { const std::string extension = BaseImporter::GetExtension(filename); - if (extension == "jpg" || extension == "png") { + if (extension == "jpg" || extension == "png" || extension == "jpeg") { std::string::size_type pos = filename.find("thumbnail"); - if (pos == std::string::npos) { + if (pos != std::string::npos) { return false; } return true; diff --git a/code/AssetLib/3MF/D3MFOpcPackage.h b/code/AssetLib/3MF/D3MFOpcPackage.h index f6803a0ef..9782752bf 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.h +++ b/code/AssetLib/3MF/D3MFOpcPackage.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/XmlSerializer.cpp b/code/AssetLib/3MF/XmlSerializer.cpp index 5fcdc0ccc..354ed19bb 100644 --- a/code/AssetLib/3MF/XmlSerializer.cpp +++ b/code/AssetLib/3MF/XmlSerializer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -75,7 +75,7 @@ aiFace ReadTriangle(XmlNode &node, int &texId0, int &texId1, int &texId2) { face.mIndices[1] = static_cast(std::atoi(node.attribute(XmlTag::v2).as_string())); face.mIndices[2] = static_cast(std::atoi(node.attribute(XmlTag::v3).as_string())); - texId0 = texId1 = texId2 = -1; + texId0 = texId1 = texId2 = IdNotSet; XmlParser::getIntAttribute(node, XmlTag::p1, texId0); XmlParser::getIntAttribute(node, XmlTag::p2, texId1); XmlParser::getIntAttribute(node, XmlTag::p3, texId2); @@ -236,6 +236,8 @@ void XmlSerializer::ImportXml(aiScene *scene) { ReadBaseMaterials(currentNode); } else if (currentNodeName == XmlTag::meta) { ReadMetadata(currentNode); + } else if (currentNodeName == XmlTag::colorgroup) { + ReadColorGroup(currentNode); } } StoreMaterialsInScene(scene); @@ -331,9 +333,49 @@ void XmlSerializer::ReadObject(XmlNode &node) { if (hasPid) { auto it = mResourcesDictionnary.find(pid); - if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) { - BaseMaterials *materials = static_cast(it->second); - mesh->mMaterialIndex = materials->mMaterialIndex[pindex]; + if (hasPindex && it != mResourcesDictionnary.end()) { + if (it->second->getType() == ResourceType::RT_BaseMaterials) { + BaseMaterials *materials = static_cast(it->second); + mesh->mMaterialIndex = materials->mMaterialIndex[pindex]; + } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) { + Texture2DGroup *group = static_cast(it->second); + if (mesh->mTextureCoords[0] == nullptr) { + mesh->mNumUVComponents[0] = 2; + for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + mesh->mNumUVComponents[i] = 0; + } + + const std::string name = ai_to_string(group->mTexId); + for (size_t i = 0; i < mMaterials.size(); ++i) { + if (name == mMaterials[i]->GetName().C_Str()) { + mesh->mMaterialIndex = static_cast(i); + } + } + + mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; + for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) { + mesh->mTextureCoords[0][vertex_idx] = + aiVector3D(group->mTex2dCoords[pindex].x, group->mTex2dCoords[pindex].y, 0.0f); + } + } else { + for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) { + if (mesh->mTextureCoords[0][vertex_idx].z < 0) { + // use default + mesh->mTextureCoords[0][vertex_idx] = + aiVector3D(group->mTex2dCoords[pindex].x, group->mTex2dCoords[pindex].y, 0.0f); + } + } + } + }else if (it->second->getType() == ResourceType::RT_ColorGroup) { + if (mesh->mColors[0] == nullptr) { + mesh->mColors[0] = new aiColor4D[mesh->mNumVertices]; + + ColorGroup *group = static_cast(it->second); + for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) { + mesh->mColors[0][vertex_idx] = group->mColors[pindex]; + } + } + } } } @@ -415,27 +457,36 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) { for (XmlNode ¤tNode : node.children()) { const std::string currentName = currentNode.name(); if (currentName == XmlTag::triangle) { - int pid = IdNotSet, p1 = IdNotSet; + int pid = IdNotSet; bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); - bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); - int texId[3]; - Texture2DGroup *group = nullptr; - aiFace face = ReadTriangle(currentNode, texId[0], texId[1], texId[2]); - if (hasPid && hasP1) { + int pindex[3]; + aiFace face = ReadTriangle(currentNode, pindex[0], pindex[1], pindex[2]); + if (hasPid && (pindex[0] != IdNotSet || pindex[1] != IdNotSet || pindex[2] != IdNotSet)) { auto it = mResourcesDictionnary.find(pid); if (it != mResourcesDictionnary.end()) { if (it->second->getType() == ResourceType::RT_BaseMaterials) { BaseMaterials *baseMaterials = static_cast(it->second); - mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; + + auto update_material = [&](int idx) { + if (pindex[idx] != IdNotSet) { + mesh->mMaterialIndex = baseMaterials->mMaterialIndex[pindex[idx]]; + } + }; + + update_material(0); + update_material(1); + update_material(2); + } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) { + // Load texture coordinates into mesh, when any + Texture2DGroup *group = static_cast(it->second); // fix bug if (mesh->mTextureCoords[0] == nullptr) { mesh->mNumUVComponents[0] = 2; for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { mesh->mNumUVComponents[i] = 0; } - group = static_cast(it->second); const std::string name = ai_to_string(group->mTexId); for (size_t i = 0; i < mMaterials.size(); ++i) { if (name == mMaterials[i]->GetName().C_Str()) { @@ -443,21 +494,44 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) { } } mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; + for (unsigned int vertex_index = 0; vertex_index < mesh->mNumVertices; vertex_index++) { + mesh->mTextureCoords[0][vertex_index].z = IdNotSet;//mark not set + } } + + auto update_texture = [&](int idx) { + if (pindex[idx] != IdNotSet) { + size_t vertex_index = face.mIndices[idx]; + mesh->mTextureCoords[0][vertex_index] = + aiVector3D(group->mTex2dCoords[pindex[idx]].x, group->mTex2dCoords[pindex[idx]].y, 0.0f); + } + }; + + update_texture(0); + update_texture(1); + update_texture(2); + + } else if (it->second->getType() == ResourceType::RT_ColorGroup) { + // Load vertex color into mesh, when any + ColorGroup *group = static_cast(it->second); + if (mesh->mColors[0] == nullptr) { + mesh->mColors[0] = new aiColor4D[mesh->mNumVertices]; + } + + auto update_color = [&](int idx) { + if (pindex[idx] != IdNotSet) { + size_t vertex_index = face.mIndices[idx]; + mesh->mColors[0][vertex_index] = group->mColors[pindex[idx]]; + } + }; + + update_color(0); + update_color(1); + update_color(2); } } } - // Load texture coordinates into mesh, when any - if (group != nullptr) { - size_t i0 = face.mIndices[0]; - size_t i1 = face.mIndices[1]; - size_t i2 = face.mIndices[2]; - mesh->mTextureCoords[0][i0] = aiVector3D(group->mTex2dCoords[texId[0]].x, group->mTex2dCoords[texId[0]].y, 0.0f); - mesh->mTextureCoords[0][i1] = aiVector3D(group->mTex2dCoords[texId[1]].x, group->mTex2dCoords[texId[1]].y, 0.0f); - mesh->mTextureCoords[0][i2] = aiVector3D(group->mTex2dCoords[texId[2]].x, group->mTex2dCoords[texId[2]].y, 0.0f); - } - faces.push_back(face); } } @@ -598,6 +672,38 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater return material; } +void XmlSerializer::ReadColor(XmlNode &node, ColorGroup *colorGroup) { + if (node.empty() || nullptr == colorGroup) { + return; + } + + for (XmlNode currentNode : node.children()) { + const std::string currentName = currentNode.name(); + if (currentName == XmlTag::color_item) { + const char *color = currentNode.attribute(XmlTag::color_vaule).as_string(); + aiColor4D color_value; + if (parseColor(color, color_value)) { + colorGroup->mColors.push_back(color_value); + } + } + } +} + +void XmlSerializer::ReadColorGroup(XmlNode &node) { + if (node.empty()) { + return; + } + + int id = IdNotSet; + if (!XmlParser::getIntAttribute(node, XmlTag::id, id)) { + return; + } + + ColorGroup *group = new ColorGroup(id); + ReadColor(node, group); + mResourcesDictionnary.insert(std::make_pair(id, group)); +} + void XmlSerializer::StoreMaterialsInScene(aiScene *scene) { if (nullptr == scene) { return; diff --git a/code/AssetLib/3MF/XmlSerializer.h b/code/AssetLib/3MF/XmlSerializer.h index 6cf6a70a9..d0700a631 100644 --- a/code/AssetLib/3MF/XmlSerializer.h +++ b/code/AssetLib/3MF/XmlSerializer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -57,6 +57,7 @@ class D3MFOpcPackage; class Object; class Texture2DGroup; class EmbeddedTexture; +class ColorGroup; class XmlSerializer { public: @@ -78,6 +79,8 @@ private: void ReadTextureGroup(XmlNode &node); aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId); void StoreMaterialsInScene(aiScene *scene); + void ReadColorGroup(XmlNode &node); + void ReadColor(XmlNode &node, ColorGroup *colorGroup); private: struct MetaEntry { diff --git a/code/AssetLib/AC/ACLoader.cpp b/code/AssetLib/AC/ACLoader.cpp index f98a4d105..242364150 100644 --- a/code/AssetLib/AC/ACLoader.cpp +++ b/code/AssetLib/AC/ACLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -77,8 +77,8 @@ static constexpr aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // skip to the next token -inline const char *AcSkipToNextToken(const char *buffer) { - if (!SkipSpaces(&buffer)) { +inline const char *AcSkipToNextToken(const char *buffer, const char *end) { + if (!SkipSpaces(&buffer, end)) { ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); } return buffer; @@ -86,13 +86,13 @@ inline const char *AcSkipToNextToken(const char *buffer) { // ------------------------------------------------------------------------------------------------ // read a string (may be enclosed in double quotation marks). buffer must point to " -inline const char *AcGetString(const char *buffer, std::string &out) { +inline const char *AcGetString(const char *buffer, const char *end, std::string &out) { if (*buffer == '\0') { throw DeadlyImportError("AC3D: Unexpected EOF in string"); } ++buffer; const char *sz = buffer; - while ('\"' != *buffer) { + while ('\"' != *buffer && buffer != end) { if (IsLineEnd(*buffer)) { ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); out = "ERROR"; @@ -112,8 +112,8 @@ inline const char *AcGetString(const char *buffer, std::string &out) { // ------------------------------------------------------------------------------------------------ // read 1 to n floats prefixed with an optional predefined identifier template -inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name, size_t name_length, size_t num, T *out) { - buffer = AcSkipToNextToken(buffer); +inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *end, const char *name, size_t name_length, size_t num, T *out) { + buffer = AcSkipToNextToken(buffer, end); if (0 != name_length) { if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { ASSIMP_LOG_ERROR("AC3D: Unexpected token. ", name, " was expected."); @@ -122,7 +122,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name buffer += name_length + 1; } for (unsigned int _i = 0; _i < num; ++_i) { - buffer = AcSkipToNextToken(buffer); + buffer = AcSkipToNextToken(buffer, end); buffer = fast_atoreal_move(buffer, ((float *)out)[_i]); } @@ -132,7 +132,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer AC3DImporter::AC3DImporter() : - buffer(), + mBuffer(), configSplitBFCull(), configEvalSubdivision(), mNumMeshes(), @@ -164,17 +164,17 @@ const aiImporterDesc *AC3DImporter::GetInfo() const { // ------------------------------------------------------------------------------------------------ // Get a pointer to the next line from the file bool AC3DImporter::GetNextLine() { - SkipLine(&buffer); - return SkipSpaces(&buffer); + SkipLine(&mBuffer.data, mBuffer.end); + return SkipSpaces(&mBuffer.data, mBuffer.end); } // ------------------------------------------------------------------------------------------------ // Parse an object section in an AC file bool AC3DImporter::LoadObjectSection(std::vector &objects) { - if (!TokenMatch(buffer, "OBJECT", 6)) + if (!TokenMatch(mBuffer.data, "OBJECT", 6)) return false; - SkipSpaces(&buffer); + SkipSpaces(&mBuffer.data, mBuffer.end); ++mNumMeshes; @@ -182,7 +182,7 @@ bool AC3DImporter::LoadObjectSection(std::vector &objects) { Object &obj = objects.back(); aiLight *light = nullptr; - if (!ASSIMP_strincmp(buffer, "light", 5)) { + if (!ASSIMP_strincmp(mBuffer.data, "light", 5)) { // This is a light source. Add it to the list mLights->push_back(light = new aiLight()); @@ -193,21 +193,21 @@ bool AC3DImporter::LoadObjectSection(std::vector &objects) { // Generate a default name for both the light source and the node // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version. - light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast(mLights->size()) - 1); + light->mName.length = ::ai_snprintf(light->mName.data, AI_MAXLEN, "ACLight_%i", static_cast(mLights->size()) - 1); obj.name = std::string(light->mName.data); ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered"); obj.type = Object::Light; - } else if (!ASSIMP_strincmp(buffer, "group", 5)) { + } else if (!ASSIMP_strincmp(mBuffer.data, "group", 5)) { obj.type = Object::Group; - } else if (!ASSIMP_strincmp(buffer, "world", 5)) { + } else if (!ASSIMP_strincmp(mBuffer.data, "world", 5)) { obj.type = Object::World; } else obj.type = Object::Poly; while (GetNextLine()) { - if (TokenMatch(buffer, "kids", 4)) { - SkipSpaces(&buffer); - unsigned int num = strtoul10(buffer, &buffer); + if (TokenMatch(mBuffer.data, "kids", 4)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + unsigned int num = strtoul10(mBuffer.data, &mBuffer.data); GetNextLine(); if (num) { // load the children of this object recursively @@ -220,51 +220,44 @@ bool AC3DImporter::LoadObjectSection(std::vector &objects) { } } return true; - } else if (TokenMatch(buffer, "name", 4)) { - SkipSpaces(&buffer); - buffer = AcGetString(buffer, obj.name); + } else if (TokenMatch(mBuffer.data, "name", 4)) { + SkipSpaces(&mBuffer.data, mBuffer.data); + mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, obj.name); // If this is a light source, we'll also need to store // the name of the node in it. if (light) { light->mName.Set(obj.name); } - } else if (TokenMatch(buffer, "texture", 7)) { - SkipSpaces(&buffer); - // skip empty acc texture - if (*buffer != '\"') { - if (!TokenMatch(buffer, "empty_texture_no_mapping", 24)) { - ASSIMP_LOG_ERROR("AC3D: Unquoted texture string"); - } - } else { - std::string texture; - buffer = AcGetString(buffer, texture); - obj.textures.push_back(texture); - } - } else if (TokenMatch(buffer, "texrep", 6)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat); + } else if (TokenMatch(mBuffer.data, "texture", 7)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + std::string texture; + mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, texture); + obj.textures.push_back(texture); + } else if (TokenMatch(mBuffer.data, "texrep", 6)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &obj.texRepeat); if (!obj.texRepeat.x || !obj.texRepeat.y) obj.texRepeat = aiVector2D(1.f, 1.f); - } else if (TokenMatch(buffer, "texoff", 6)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texOffset); - } else if (TokenMatch(buffer, "rot", 3)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 9, &obj.rotation); - } else if (TokenMatch(buffer, "loc", 3)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &obj.translation); - } else if (TokenMatch(buffer, "subdiv", 6)) { - SkipSpaces(&buffer); - obj.subDiv = strtoul10(buffer, &buffer); - } else if (TokenMatch(buffer, "crease", 6)) { - SkipSpaces(&buffer); - obj.crease = fast_atof(buffer); - } else if (TokenMatch(buffer, "numvert", 7)) { - SkipSpaces(&buffer); + } else if (TokenMatch(mBuffer.data, "texoff", 6)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &obj.texOffset); + } else if (TokenMatch(mBuffer.data, "rot", 3)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 9, &obj.rotation); + } else if (TokenMatch(mBuffer.data, "loc", 3)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 3, &obj.translation); + } else if (TokenMatch(mBuffer.data, "subdiv", 6)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + obj.subDiv = strtoul10(mBuffer.data, &mBuffer.data); + } else if (TokenMatch(mBuffer.data, "crease", 6)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + obj.crease = fast_atof(mBuffer.data); + } else if (TokenMatch(mBuffer.data, "numvert", 7)) { + SkipSpaces(&mBuffer.data, mBuffer.end); - unsigned int t = strtoul10(buffer, &buffer); + unsigned int t = strtoul10(mBuffer.data, &mBuffer.data); if (t >= AI_MAX_ALLOC(aiVector3D)) { throw DeadlyImportError("AC3D: Too many vertices, would run out of memory"); } @@ -273,59 +266,59 @@ bool AC3DImporter::LoadObjectSection(std::vector &objects) { if (!GetNextLine()) { ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet"); break; - } else if (!IsNumeric(*buffer)) { + } else if (!IsNumeric(*mBuffer.data)) { ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet"); - --buffer; // make sure the line is processed a second time + --mBuffer.data; // make sure the line is processed a second time break; } obj.vertices.emplace_back(); aiVector3D &v = obj.vertices.back(); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 3, &v.x); } - } else if (TokenMatch(buffer, "numsurf", 7)) { - SkipSpaces(&buffer); + } else if (TokenMatch(mBuffer.data, "numsurf", 7)) { + SkipSpaces(&mBuffer.data, mBuffer.end); bool Q3DWorkAround = false; - const unsigned int t = strtoul10(buffer, &buffer); + const unsigned int t = strtoul10(mBuffer.data, &mBuffer.data); obj.surfaces.reserve(t); for (unsigned int i = 0; i < t; ++i) { GetNextLine(); - if (!TokenMatch(buffer, "SURF", 4)) { + if (!TokenMatch(mBuffer.data, "SURF", 4)) { // FIX: this can occur for some files - Quick 3D for // example writes no surf chunks if (!Q3DWorkAround) { ASSIMP_LOG_WARN("AC3D: SURF token was expected"); ASSIMP_LOG_VERBOSE_DEBUG("Continuing with Quick3D Workaround enabled"); } - --buffer; // make sure the line is processed a second time + --mBuffer.data; // make sure the line is processed a second time // break; --- see fix notes above Q3DWorkAround = true; } - SkipSpaces(&buffer); + SkipSpaces(&mBuffer.data, mBuffer.end); obj.surfaces.emplace_back(); Surface &surf = obj.surfaces.back(); - surf.flags = strtoul_cppstyle(buffer); + surf.flags = strtoul_cppstyle(mBuffer.data); while (true) { if (!GetNextLine()) { throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete"); } - if (TokenMatch(buffer, "mat", 3)) { - SkipSpaces(&buffer); - surf.mat = strtoul10(buffer); - } else if (TokenMatch(buffer, "refs", 4)) { + if (TokenMatch(mBuffer.data, "mat", 3)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + surf.mat = strtoul10(mBuffer.data); + } else if (TokenMatch(mBuffer.data, "refs", 4)) { // --- see fix notes above if (Q3DWorkAround) { if (!surf.entries.empty()) { - buffer -= 6; + mBuffer.data -= 6; break; } } - SkipSpaces(&buffer); - const unsigned int m = strtoul10(buffer); + SkipSpaces(&mBuffer.data, mBuffer.end); + const unsigned int m = strtoul10(mBuffer.data); surf.entries.reserve(m); obj.numRefs += m; @@ -338,12 +331,12 @@ bool AC3DImporter::LoadObjectSection(std::vector &objects) { surf.entries.emplace_back(); Surface::SurfaceEntry &entry = surf.entries.back(); - entry.first = strtoul10(buffer, &buffer); - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &entry.second); + entry.first = strtoul10(mBuffer.data, &mBuffer.data); + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &entry.second); } } else { - --buffer; // make sure the line is processed a second time + --mBuffer.data; // make sure the line is processed a second time break; } } @@ -475,16 +468,15 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, } switch ((*it).GetType()) { - // closed line - case Surface::ClosedLine: - needMat[idx].first += (unsigned int)(*it).entries.size(); - needMat[idx].second += (unsigned int)(*it).entries.size() << 1u; + case Surface::ClosedLine: // closed line + needMat[idx].first += static_cast((*it).entries.size()); + needMat[idx].second += static_cast((*it).entries.size() << 1u); break; // unclosed line case Surface::OpenLine: - needMat[idx].first += (unsigned int)(*it).entries.size() - 1; - needMat[idx].second += ((unsigned int)(*it).entries.size() - 1) << 1u; + needMat[idx].first += static_cast((*it).entries.size() - 1); + needMat[idx].second += static_cast(((*it).entries.size() - 1) << 1u); break; // triangle strip @@ -704,18 +696,18 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, // generate a name depending on the type of the node switch (object.type) { case Object::Group: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++); + node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACGroup_%i", mGroupsCounter++); break; case Object::Poly: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++); + node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACPoly_%i", mPolysCounter++); break; case Object::Light: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++); + node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACLight_%i", mLightsCounter++); break; // there shouldn't be more than one world, but we don't care case Object::World: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++); + node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACWorld_%i", mWorldsCounter++); break; } } @@ -763,17 +755,18 @@ void AC3DImporter::InternReadFile(const std::string &pFile, std::vector mBuffer2; TextFileToBuffer(file.get(), mBuffer2); - buffer = &mBuffer2[0]; + mBuffer.data = &mBuffer2[0]; + mBuffer.end = &mBuffer2[0] + mBuffer2.size(); mNumMeshes = 0; mLightsCounter = mPolysCounter = mWorldsCounter = mGroupsCounter = 0; - if (::strncmp(buffer, "AC3D", 4)) { + if (::strncmp(mBuffer.data, "AC3D", 4)) { throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found"); } // print the file format version to the console - unsigned int version = HexDigitToDecimal(buffer[4]); + unsigned int version = HexDigitToDecimal(mBuffer.data[4]); char msg[3]; ASSIMP_itoa10(msg, 3, version); ASSIMP_LOG_INFO("AC3D file format version: ", msg); @@ -788,31 +781,31 @@ void AC3DImporter::InternReadFile(const std::string &pFile, mLights = &lights; while (GetNextLine()) { - if (TokenMatch(buffer, "MATERIAL", 8)) { + if (TokenMatch(mBuffer.data, "MATERIAL", 8)) { materials.emplace_back(); Material &mat = materials.back(); // manually parse the material ... sscanf would use the buldin atof ... // Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f - buffer = AcSkipToNextToken(buffer); - if ('\"' == *buffer) { - buffer = AcGetString(buffer, mat.name); - buffer = AcSkipToNextToken(buffer); + mBuffer.data = AcSkipToNextToken(mBuffer.data, mBuffer.end); + if ('\"' == *mBuffer.data) { + mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, mat.name); + mBuffer.data = AcSkipToNextToken(mBuffer.data, mBuffer.end); } - buffer = TAcCheckedLoadFloatArray(buffer, "rgb", 3, 3, &mat.rgb); - buffer = TAcCheckedLoadFloatArray(buffer, "amb", 3, 3, &mat.amb); - buffer = TAcCheckedLoadFloatArray(buffer, "emis", 4, 3, &mat.emis); - buffer = TAcCheckedLoadFloatArray(buffer, "spec", 4, 3, &mat.spec); - buffer = TAcCheckedLoadFloatArray(buffer, "shi", 3, 1, &mat.shin); - buffer = TAcCheckedLoadFloatArray(buffer, "trans", 5, 1, &mat.trans); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "rgb", 3, 3, &mat.rgb); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "amb", 3, 3, &mat.amb); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "emis", 4, 3, &mat.emis); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "spec", 4, 3, &mat.spec); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "shi", 3, 1, &mat.shin); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "trans", 5, 1, &mat.trans); } else { LoadObjectSection(rootObjects); } } - if (rootObjects.empty() || !mNumMeshes) { + if (rootObjects.empty() || mNumMeshes == 0u) { throw DeadlyImportError("AC3D: No meshes have been loaded"); } if (materials.empty()) { @@ -828,7 +821,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile, materials.reserve(mNumMeshes); // generate a dummy root if there are multiple objects on the top layer - Object *root; + Object *root = nullptr; if (1 == rootObjects.size()) root = &rootObjects[0]; else { @@ -841,7 +834,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile, delete root; } - if (!::strncmp(pScene->mRootNode->mName.data, "Node", 4)) { + if (::strncmp(pScene->mRootNode->mName.data, "Node", 4) == 0) { pScene->mRootNode->mName.Set(""); } @@ -860,7 +853,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile, // copy lights pScene->mNumLights = (unsigned int)lights.size(); - if (lights.size()) { + if (!lights.empty()) { pScene->mLights = new aiLight *[lights.size()]; ::memcpy(pScene->mLights, &lights[0], lights.size() * sizeof(void *)); } diff --git a/code/AssetLib/AC/ACLoader.h b/code/AssetLib/AC/ACLoader.h index 3b5be4b6e..22f7d0d09 100644 --- a/code/AssetLib/AC/ACLoader.h +++ b/code/AssetLib/AC/ACLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -242,7 +242,7 @@ private: private: // points to the next data line - const char *buffer; + aiBuffer mBuffer; // Configuration option: if enabled, up to two meshes // are generated per material: those faces who have diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index eabdb35e1..7c0d3b4e9 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/AMF/AMFImporter.hpp b/code/AssetLib/AMF/AMFImporter.hpp index fbaf4fc6d..50be465ce 100644 --- a/code/AssetLib/AMF/AMFImporter.hpp +++ b/code/AssetLib/AMF/AMFImporter.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/AMF/AMFImporter_Geometry.cpp b/code/AssetLib/AMF/AMFImporter_Geometry.cpp index 341999f56..db262dfbd 100644 --- a/code/AssetLib/AMF/AMFImporter_Geometry.cpp +++ b/code/AssetLib/AMF/AMFImporter_Geometry.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/AMF/AMFImporter_Material.cpp b/code/AssetLib/AMF/AMFImporter_Material.cpp index 676e74856..ae27f5d37 100644 --- a/code/AssetLib/AMF/AMFImporter_Material.cpp +++ b/code/AssetLib/AMF/AMFImporter_Material.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/AMF/AMFImporter_Node.hpp b/code/AssetLib/AMF/AMFImporter_Node.hpp index dd27316d3..21068a9ba 100644 --- a/code/AssetLib/AMF/AMFImporter_Node.hpp +++ b/code/AssetLib/AMF/AMFImporter_Node.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp index d5160870a..969c64bd2 100644 --- a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp +++ b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/ASE/ASELoader.cpp b/code/AssetLib/ASE/ASELoader.cpp index f98316661..7e411fc03 100644 --- a/code/AssetLib/ASE/ASELoader.cpp +++ b/code/AssetLib/ASE/ASELoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/ASE/ASELoader.h b/code/AssetLib/ASE/ASELoader.h index 2509671ef..5654fa630 100644 --- a/code/AssetLib/ASE/ASELoader.h +++ b/code/AssetLib/ASE/ASELoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp index 90f462598..c071ae900 100644 --- a/code/AssetLib/ASE/ASEParser.cpp +++ b/code/AssetLib/ASE/ASEParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -110,10 +110,12 @@ using namespace Assimp::ASE; ++filePtr; // ------------------------------------------------------------------------------------------------ -Parser::Parser(const char *szFile, unsigned int fileFormatDefault) { +Parser::Parser(const char *szFile, unsigned int fileFormatDefault) : + filePtr(nullptr), mEnd (nullptr) { ai_assert(nullptr != szFile); filePtr = szFile; + mEnd = filePtr + std::strlen(filePtr); iFileFormat = fileFormatDefault; // make sure that the color values are invalid @@ -179,14 +181,22 @@ bool Parser::SkipToNextToken() { while (true) { char me = *filePtr; + if (filePtr == mEnd) { + return false; + } + // increase the line number counter if necessary if (IsLineEnd(me) && !bLastWasEndLine) { ++iLineNumber; bLastWasEndLine = true; } else bLastWasEndLine = false; - if ('*' == me || '}' == me || '{' == me) return true; - if ('\0' == me) return false; + if ('*' == me || '}' == me || '{' == me) { + return true; + } + if ('\0' == me) { + return false; + } ++filePtr; } @@ -344,8 +354,9 @@ void Parser::ParseLV1SoftSkinBlock() { unsigned int numVerts = 0; const char *sz = filePtr; - while (!IsSpaceOrNewLine(*filePtr)) + while (!IsSpaceOrNewLine(*filePtr)) { ++filePtr; + } const unsigned int diff = (unsigned int)(filePtr - sz); if (diff) { @@ -363,24 +374,24 @@ void Parser::ParseLV1SoftSkinBlock() { // Skip the mesh data - until we find a new mesh // or the end of the *MESH_SOFTSKINVERTS section while (true) { - SkipSpacesAndLineEnd(&filePtr); + SkipSpacesAndLineEnd(&filePtr, mEnd); if (*filePtr == '}') { ++filePtr; return; } else if (!IsNumeric(*filePtr)) break; - SkipLine(&filePtr); + SkipLine(&filePtr, mEnd); } } else { - SkipSpacesAndLineEnd(&filePtr); + SkipSpacesAndLineEnd(&filePtr, mEnd); ParseLV4MeshLong(numVerts); // Reserve enough storage curMesh->mBoneVertices.reserve(numVerts); for (unsigned int i = 0; i < numVerts; ++i) { - SkipSpacesAndLineEnd(&filePtr); + SkipSpacesAndLineEnd(&filePtr, mEnd); unsigned int numWeights; ParseLV4MeshLong(numWeights); @@ -422,7 +433,7 @@ void Parser::ParseLV1SoftSkinBlock() { if (*filePtr == '\0') return; ++filePtr; - SkipSpacesAndLineEnd(&filePtr); + SkipSpacesAndLineEnd(&filePtr, mEnd); } } @@ -489,13 +500,19 @@ void Parser::ParseLV1MaterialListBlock() { continue; } if (TokenMatch(filePtr, "MATERIAL", 8)) { + // ensure we have at least one material allocated + if (iMaterialCount == 0) { + LogWarning("*MATERIAL_COUNT unspecified or 0"); + iMaterialCount = 1; + m_vMaterials.resize(iOldMaterialCount + iMaterialCount, Material("INVALID")); + } + unsigned int iIndex = 0; ParseLV4MeshLong(iIndex); if (iIndex >= iMaterialCount) { LogWarning("Out of range: material index is too large"); iIndex = iMaterialCount - 1; - return; } // get a reference to the material @@ -642,6 +659,12 @@ void Parser::ParseLV2MaterialBlock(ASE::Material &mat) { } // submaterial chunks if (TokenMatch(filePtr, "SUBMATERIAL", 11)) { + // ensure we have at least one material allocated + if (iNumSubMaterials == 0) { + LogWarning("*NUMSUBMTLS unspecified or 0"); + iNumSubMaterials = 1; + mat.avSubMaterials.resize(iNumSubMaterials, Material("INVALID SUBMATERIAL")); + } unsigned int iIndex = 0; ParseLV4MeshLong(iIndex); @@ -743,7 +766,7 @@ void Parser::ParseLV3MapBlock(Texture &map) { // ------------------------------------------------------------------------------------------------ bool Parser::ParseString(std::string &out, const char *szName) { char szBuffer[1024]; - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Unexpected EOL", szName); LogWarning(szBuffer); @@ -1355,7 +1378,7 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones, ASE::Mesh &mesh) { // Mesh bone with name ... if (TokenMatch(filePtr, "MESH_BONE_NAME", 14)) { // parse an index ... - if (SkipSpaces(&filePtr)) { + if (SkipSpaces(&filePtr, mEnd)) { unsigned int iIndex = strtoul10(filePtr, &filePtr); if (iIndex >= iNumBones) { LogWarning("Bone index is out of bounds"); @@ -1395,11 +1418,11 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes std::pair pairOut; while (true) { // first parse the bone index ... - if (!SkipSpaces(&filePtr)) break; + if (!SkipSpaces(&filePtr, mEnd)) break; pairOut.first = strtoul10(filePtr, &filePtr); // then parse the vertex weight - if (!SkipSpaces(&filePtr)) break; + if (!SkipSpaces(&filePtr, mEnd)) break; filePtr = fast_atoreal_move(filePtr, pairOut.second); // -1 marks unused entries @@ -1675,7 +1698,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) { // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshFace(ASE::Face &out) { // skip spaces and tabs - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]"); SkipToNextToken(); return; @@ -1685,7 +1708,7 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { out.iFace = strtoul10(filePtr, &filePtr); // next character should be ':' - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { // FIX: there are some ASE files which haven't got : here .... LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]"); SkipToNextToken(); @@ -1697,7 +1720,7 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { // Parse all mesh indices for (unsigned int i = 0; i < 3; ++i) { unsigned int iIndex = 0; - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL"); SkipToNextToken(); return; @@ -1723,7 +1746,7 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { ++filePtr; // next character should be ':' - if (!SkipSpaces(&filePtr) || ':' != *filePtr) { + if (!SkipSpaces(&filePtr, mEnd) || ':' != *filePtr) { LogWarning("Unable to parse *MESH_FACE Element: " "Unexpected EOL. \':\' expected [#2]"); SkipToNextToken(); @@ -1731,9 +1754,9 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { } ++filePtr; - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " - "Vertex index ecpected [#4]"); + "Vertex index expected [#4]"); SkipToNextToken(); return; } @@ -1752,7 +1775,7 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { // parse the smoothing group of the face if (TokenMatch(filePtr, "*MESH_SMOOTHING", 15)) { - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { LogWarning("Unable to parse *MESH_SMOOTHING Element: " "Unexpected EOL. Smoothing group(s) expected [#5]"); SkipToNextToken(); @@ -1771,12 +1794,12 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { LogWarning(message.c_str()); } } - SkipSpaces(&filePtr); + SkipSpaces(&filePtr, mEnd); if (',' != *filePtr) { break; } ++filePtr; - SkipSpaces(&filePtr); + SkipSpaces(&filePtr, mEnd); } } @@ -1792,7 +1815,7 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { } if (TokenMatch(filePtr, "*MESH_MTLID", 11)) { - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. " "Material index expected [#6]"); SkipToNextToken(); @@ -1840,7 +1863,7 @@ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) { // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshFloat(ai_real &fOut) { // skip spaces and tabs - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { // LOG LogWarning("Unable to parse float: unexpected EOL [#1]"); fOut = 0.0; @@ -1853,7 +1876,7 @@ void Parser::ParseLV4MeshFloat(ai_real &fOut) { // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshLong(unsigned int &iOut) { // Skip spaces and tabs - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&filePtr, mEnd)) { // LOG LogWarning("Unable to parse long: unexpected EOL [#1]"); iOut = 0; diff --git a/code/AssetLib/ASE/ASEParser.h b/code/AssetLib/ASE/ASEParser.h index c41cd59d3..263b5ca73 100644 --- a/code/AssetLib/ASE/ASEParser.h +++ b/code/AssetLib/ASE/ASEParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -620,6 +620,9 @@ public: //! Pointer to current data const char *filePtr; + /// The end pointer of the file data + const char *mEnd; + //! background color to be passed to the viewer //! QNAN if none was found aiColor3D m_clrBackground; diff --git a/code/AssetLib/Assbin/AssbinExporter.cpp b/code/AssetLib/Assbin/AssbinExporter.cpp index 149b3c5f3..b8465f866 100644 --- a/code/AssetLib/Assbin/AssbinExporter.cpp +++ b/code/AssetLib/Assbin/AssbinExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinExporter.h b/code/AssetLib/Assbin/AssbinExporter.h index 8b721994d..271b6b833 100644 --- a/code/AssetLib/Assbin/AssbinExporter.h +++ b/code/AssetLib/Assbin/AssbinExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinFileWriter.cpp b/code/AssetLib/Assbin/AssbinFileWriter.cpp index 782595bc1..90bcccf90 100644 --- a/code/AssetLib/Assbin/AssbinFileWriter.cpp +++ b/code/AssetLib/Assbin/AssbinFileWriter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinFileWriter.h b/code/AssetLib/Assbin/AssbinFileWriter.h index cfed3b400..84641df46 100644 --- a/code/AssetLib/Assbin/AssbinFileWriter.h +++ b/code/AssetLib/Assbin/AssbinFileWriter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinLoader.cpp b/code/AssetLib/Assbin/AssbinLoader.cpp index 6995ea976..d2566a85c 100644 --- a/code/AssetLib/Assbin/AssbinLoader.cpp +++ b/code/AssetLib/Assbin/AssbinLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinLoader.h b/code/AssetLib/Assbin/AssbinLoader.h index f922b91fd..2b85e6655 100644 --- a/code/AssetLib/Assbin/AssbinLoader.h +++ b/code/AssetLib/Assbin/AssbinLoader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assxml/AssxmlExporter.cpp b/code/AssetLib/Assxml/AssxmlExporter.cpp index 731916a25..b9691b822 100644 --- a/code/AssetLib/Assxml/AssxmlExporter.cpp +++ b/code/AssetLib/Assxml/AssxmlExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assxml/AssxmlExporter.h b/code/AssetLib/Assxml/AssxmlExporter.h index 6fcdebfab..28a9b7f35 100644 --- a/code/AssetLib/Assxml/AssxmlExporter.h +++ b/code/AssetLib/Assxml/AssxmlExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.cpp b/code/AssetLib/Assxml/AssxmlFileWriter.cpp index 8f8e76bd2..f6fdc4a0c 100644 --- a/code/AssetLib/Assxml/AssxmlFileWriter.cpp +++ b/code/AssetLib/Assxml/AssxmlFileWriter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.h b/code/AssetLib/Assxml/AssxmlFileWriter.h index 0620c9db7..1051a03a0 100644 --- a/code/AssetLib/Assxml/AssxmlFileWriter.h +++ b/code/AssetLib/Assxml/AssxmlFileWriter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/B3D/B3DImporter.cpp b/code/AssetLib/B3D/B3DImporter.cpp index 670f3de53..d0029277c 100644 --- a/code/AssetLib/B3D/B3DImporter.cpp +++ b/code/AssetLib/B3D/B3DImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/B3D/B3DImporter.h b/code/AssetLib/B3D/B3DImporter.h index e47d9078b..0fcfae620 100644 --- a/code/AssetLib/B3D/B3DImporter.h +++ b/code/AssetLib/B3D/B3DImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/BVH/BVHLoader.cpp b/code/AssetLib/BVH/BVHLoader.cpp index 4d2cfde15..2b37286ea 100644 --- a/code/AssetLib/BVH/BVHLoader.cpp +++ b/code/AssetLib/BVH/BVHLoader.cpp @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/AssetLib/BVH/BVHLoader.h b/code/AssetLib/BVH/BVHLoader.h index 56c32bd99..2c5e24114 100644 --- a/code/AssetLib/BVH/BVHLoader.h +++ b/code/AssetLib/BVH/BVHLoader.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderBMesh.cpp b/code/AssetLib/Blender/BlenderBMesh.cpp index a82e7c678..0660967bd 100644 --- a/code/AssetLib/Blender/BlenderBMesh.cpp +++ b/code/AssetLib/Blender/BlenderBMesh.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/Blender/BlenderBMesh.h b/code/AssetLib/Blender/BlenderBMesh.h index 7d2f71717..1798aaf74 100644 --- a/code/AssetLib/Blender/BlenderBMesh.h +++ b/code/AssetLib/Blender/BlenderBMesh.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/Blender/BlenderDNA.cpp b/code/AssetLib/Blender/BlenderDNA.cpp index d22c4bfd7..311911249 100644 --- a/code/AssetLib/Blender/BlenderDNA.cpp +++ b/code/AssetLib/Blender/BlenderDNA.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderDNA.h b/code/AssetLib/Blender/BlenderDNA.h index 494dc4b34..f6a691fd6 100644 --- a/code/AssetLib/Blender/BlenderDNA.h +++ b/code/AssetLib/Blender/BlenderDNA.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderDNA.inl b/code/AssetLib/Blender/BlenderDNA.inl index 4f64987a5..9bcb602ba 100644 --- a/code/AssetLib/Blender/BlenderDNA.inl +++ b/code/AssetLib/Blender/BlenderDNA.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderIntermediate.h b/code/AssetLib/Blender/BlenderIntermediate.h index 546b79f09..700beb7b0 100644 --- a/code/AssetLib/Blender/BlenderIntermediate.h +++ b/code/AssetLib/Blender/BlenderIntermediate.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp index 35b35f08d..923eb5959 100644 --- a/code/AssetLib/Blender/BlenderLoader.cpp +++ b/code/AssetLib/Blender/BlenderLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -359,7 +359,7 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M // check if the file contents are bundled with the BLEND file if (img->packedfile) { name.data[0] = '*'; - name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(MAXLEN - 1), static_cast(conv_data.textures->size())); + name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(AI_MAXLEN - 1), static_cast(conv_data.textures->size())); conv_data.textures->push_back(new aiTexture()); aiTexture *curTex = conv_data.textures->back(); @@ -433,7 +433,7 @@ void BlenderImporter::AddSentinelTexture(aiMaterial *out, const Material *mat, c (void)conv_data; aiString name; - name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++, + name.length = ai_snprintf(name.data, AI_MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++, GetTextureTypeDisplayString(tex->tex->type)); out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE( conv_data.next_texture[aiTextureType_DIFFUSE]++)); diff --git a/code/AssetLib/Blender/BlenderLoader.h b/code/AssetLib/Blender/BlenderLoader.h index 2bdc24ae2..5c800c627 100644 --- a/code/AssetLib/Blender/BlenderLoader.h +++ b/code/AssetLib/Blender/BlenderLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderModifier.cpp b/code/AssetLib/Blender/BlenderModifier.cpp index f925de608..2cd8bda7c 100644 --- a/code/AssetLib/Blender/BlenderModifier.cpp +++ b/code/AssetLib/Blender/BlenderModifier.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderModifier.h b/code/AssetLib/Blender/BlenderModifier.h index 180a456a1..2d6940357 100644 --- a/code/AssetLib/Blender/BlenderModifier.h +++ b/code/AssetLib/Blender/BlenderModifier.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderScene.h b/code/AssetLib/Blender/BlenderScene.h index ba7ded909..671891c68 100644 --- a/code/AssetLib/Blender/BlenderScene.h +++ b/code/AssetLib/Blender/BlenderScene.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderTessellator.cpp b/code/AssetLib/Blender/BlenderTessellator.cpp index 84bc2ea1a..f51cf9780 100644 --- a/code/AssetLib/Blender/BlenderTessellator.cpp +++ b/code/AssetLib/Blender/BlenderTessellator.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderTessellator.h b/code/AssetLib/Blender/BlenderTessellator.h index 21a4f4701..e43535f6c 100644 --- a/code/AssetLib/Blender/BlenderTessellator.h +++ b/code/AssetLib/Blender/BlenderTessellator.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/C4D/C4DImporter.cpp b/code/AssetLib/C4D/C4DImporter.cpp index c11ec0280..daef6ebe4 100644 --- a/code/AssetLib/C4D/C4DImporter.cpp +++ b/code/AssetLib/C4D/C4DImporter.cpp @@ -46,10 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // no #ifdefing here, Cinema4D support is carried out in a branch of assimp // where it is turned on in the CMake settings. -#ifndef _MSC_VER -# error C4D support is currently MSVC only -#endif - #include "C4DImporter.h" #include #include @@ -111,7 +107,7 @@ C4DImporter::C4DImporter() = default; C4DImporter::~C4DImporter() = default; // ------------------------------------------------------------------------------------------------ -bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const { +bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { const std::string& extension = GetExtension(pFile); if (extension == "c4d") { return true; @@ -305,7 +301,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) { // based on Cineware sample code while (object) { - const LONG type = object->GetType(); + const Int32 type = object->GetType(); const Matrix& ml = object->GetMl(); aiNode* const nd = new aiNode(); @@ -368,8 +364,8 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) { PolygonObject* const polyObject = dynamic_cast(object); ai_assert(polyObject != nullptr); - const LONG pointCount = polyObject->GetPointCount(); - const LONG polyCount = polyObject->GetPolygonCount(); + const Int32 pointCount = polyObject->GetPointCount(); + const Int32 polyCount = polyObject->GetPolygonCount(); if(!polyObject || !pointCount) { LogWarn("ignoring mesh with zero vertices or faces"); return nullptr; @@ -391,7 +387,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) { unsigned int vcount = 0; // first count vertices - for (LONG i = 0; i < polyCount; i++) + for (Int32 i = 0; i < polyCount; i++) { vcount += 3; @@ -434,7 +430,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) { } // copy vertices and extra channels over and populate faces - for (LONG i = 0; i < polyCount; ++i, ++face) { + for (Int32 i = 0; i < polyCount; ++i, ++face) { ai_assert(polys[i].a < pointCount && polys[i].a >= 0); const Vector& pointA = points[polys[i].a]; verts->x = pointA.x; @@ -511,7 +507,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) { if (tangents_src) { for(unsigned int k = 0; k < face->mNumIndices; ++k) { - LONG l; + Int32 l; switch(k) { case 0: l = polys[i].a; diff --git a/code/AssetLib/C4D/C4DImporter.h b/code/AssetLib/C4D/C4DImporter.h index c44cf5e37..effd2af09 100644 --- a/code/AssetLib/C4D/C4DImporter.h +++ b/code/AssetLib/C4D/C4DImporter.h @@ -78,6 +78,8 @@ namespace Assimp { // ------------------------------------------------------------------------------------------- class C4DImporter : public BaseImporter, public LogFunctions { public: + C4DImporter(); + ~C4DImporter() override; bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override; protected: diff --git a/code/AssetLib/COB/COBLoader.cpp b/code/AssetLib/COB/COBLoader.cpp index 9a6e32f6d..f0899bddd 100644 --- a/code/AssetLib/COB/COBLoader.cpp +++ b/code/AssetLib/COB/COBLoader.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -473,8 +473,9 @@ void COBImporter::ReadBasicNodeInfo_Ascii(Node &msh, LineSplitter &splitter, con } else if (splitter.match_start("Transform")) { for (unsigned int y = 0; y < 4 && ++splitter; ++y) { const char *s = splitter->c_str(); + const char *end = s + splitter->size(); for (unsigned int x = 0; x < 4; ++x) { - SkipSpaces(&s); + SkipSpaces(&s, end); msh.transform[y][x] = fast_atof(&s); } } @@ -486,12 +487,12 @@ void COBImporter::ReadBasicNodeInfo_Ascii(Node &msh, LineSplitter &splitter, con // ------------------------------------------------------------------------------------------------ template -void COBImporter::ReadFloat3Tuple_Ascii(T &fill, const char **in) { +void COBImporter::ReadFloat3Tuple_Ascii(T &fill, const char **in, const char *end) { const char *rgb = *in; for (unsigned int i = 0; i < 3; ++i) { - SkipSpaces(&rgb); + SkipSpaces(&rgb, end); if (*rgb == ',') ++rgb; - SkipSpaces(&rgb); + SkipSpaces(&rgb, end); fill[i] = fast_atof(&rgb); } @@ -538,7 +539,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk } const char *rgb = splitter[1]; - ReadFloat3Tuple_Ascii(mat.rgb, &rgb); + ReadFloat3Tuple_Ascii(mat.rgb, &rgb, splitter.getEnd()); ++splitter; if (!splitter.match_start("alpha ")) { @@ -617,20 +618,21 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk } const char *rgb = splitter[1]; - ReadFloat3Tuple_Ascii(msh.color, &rgb); + const char *end = splitter.getEnd(); + ReadFloat3Tuple_Ascii(msh.color, &rgb, end); - SkipSpaces(&rgb); + SkipSpaces(&rgb, end); if (strncmp(rgb, "cone angle", 10) != 0) { ASSIMP_LOG_WARN("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id); } - SkipSpaces(rgb + 10, &rgb); + SkipSpaces(rgb + 10, &rgb, end); msh.angle = fast_atof(&rgb); - SkipSpaces(&rgb); + SkipSpaces(&rgb, end); if (strncmp(rgb, "inner angle", 11) != 0) { ASSIMP_LOG_WARN("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id); } - SkipSpaces(rgb + 11, &rgb); + SkipSpaces(rgb + 11, &rgb, end); msh.inner_angle = fast_atof(&rgb); // skip the rest for we can't handle this kind of physically-based lighting information. @@ -703,14 +705,14 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk for (unsigned int cur = 0; cur < cnt && ++splitter; ++cur) { const char *s = splitter->c_str(); - + const char *end = splitter.getEnd(); aiVector3D &v = msh.vertex_positions[cur]; - SkipSpaces(&s); + SkipSpaces(&s, end); v.x = fast_atof(&s); - SkipSpaces(&s); + SkipSpaces(&s, end); v.y = fast_atof(&s); - SkipSpaces(&s); + SkipSpaces(&s, end); v.z = fast_atof(&s); } } else if (splitter.match_start("Texture Vertices")) { @@ -719,12 +721,13 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk for (unsigned int cur = 0; cur < cnt && ++splitter; ++cur) { const char *s = splitter->c_str(); + const char *end = splitter.getEnd(); aiVector2D &v = msh.texture_coords[cur]; - SkipSpaces(&s); + SkipSpaces(&s, end); v.x = fast_atof(&s); - SkipSpaces(&s); + SkipSpaces(&s, end); v.y = fast_atof(&s); } } else if (splitter.match_start("Faces")) { @@ -749,8 +752,9 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk face.material = strtoul10(splitter[6]); const char *s = (++splitter)->c_str(); + const char *end = splitter.getEnd(); for (size_t i = 0; i < face.indices.size(); ++i) { - if (!SkipSpaces(&s)) { + if (!SkipSpaces(&s, end)) { ThrowException("Expected EOL token in Face entry"); } if ('<' != *s++) { diff --git a/code/AssetLib/COB/COBLoader.h b/code/AssetLib/COB/COBLoader.h index a9755f5d7..ec3c7756b 100644 --- a/code/AssetLib/COB/COBLoader.h +++ b/code/AssetLib/COB/COBLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -120,7 +120,7 @@ private: void ReadChunkInfo_Ascii(COB::ChunkInfo &out, const LineSplitter &splitter); void ReadBasicNodeInfo_Ascii(COB::Node &msh, LineSplitter &splitter, const COB::ChunkInfo &nfo); template - void ReadFloat3Tuple_Ascii(T &fill, const char **in); + void ReadFloat3Tuple_Ascii(T &fill, const char **in, const char *end); void ReadPolH_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo); void ReadBitM_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo); diff --git a/code/AssetLib/COB/COBScene.h b/code/AssetLib/COB/COBScene.h index cc49de276..ea4c01251 100644 --- a/code/AssetLib/COB/COBScene.h +++ b/code/AssetLib/COB/COBScene.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/CSM/CSMLoader.cpp b/code/AssetLib/CSM/CSMLoader.cpp index 20f2343f5..47beee514 100644 --- a/code/AssetLib/CSM/CSMLoader.cpp +++ b/code/AssetLib/CSM/CSMLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team @@ -82,23 +82,20 @@ CSMImporter::CSMImporter() : noSkeletonMesh(){ // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const -{ +bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { static const char* tokens[] = {"$Filename"}; return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ // Build a string of all file extensions supported -const aiImporterDesc* CSMImporter::GetInfo () const -{ +const aiImporterDesc* CSMImporter::GetInfo () const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties for the loader -void CSMImporter::SetupProperties(const Importer* pImp) -{ +void CSMImporter::SetupProperties(const Importer* pImp) { noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; } @@ -118,29 +115,29 @@ void CSMImporter::InternReadFile( const std::string& pFile, std::vector mBuffer2; TextFileToBuffer(file.get(),mBuffer2); const char* buffer = &mBuffer2[0]; - + const char *end = &mBuffer2[mBuffer2.size() - 1] + 1; std::unique_ptr anim(new aiAnimation()); int first = 0, last = 0x00ffffff; // now process the file and look out for '$' sections while (true) { - SkipSpaces(&buffer); + SkipSpaces(&buffer, end); if ('\0' == *buffer) break; if ('$' == *buffer) { ++buffer; if (TokenMatchI(buffer,"firstframe",10)) { - SkipSpaces(&buffer); + SkipSpaces(&buffer, end); first = strtol10(buffer,&buffer); } else if (TokenMatchI(buffer,"lastframe",9)) { - SkipSpaces(&buffer); + SkipSpaces(&buffer, end); last = strtol10(buffer,&buffer); } else if (TokenMatchI(buffer,"rate",4)) { - SkipSpaces(&buffer); - float d; + SkipSpaces(&buffer, end); + float d = { 0.0f }; buffer = fast_atoreal_move(buffer,d); anim->mTicksPerSecond = d; } @@ -148,8 +145,8 @@ void CSMImporter::InternReadFile( const std::string& pFile, std::vector< aiNodeAnim* > anims_temp; anims_temp.reserve(30); while (true) { - SkipSpaces(&buffer); - if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$') + SkipSpaces(&buffer, end); + if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer, end) && *buffer == '$') break; // next section // Construct a new node animation channel and setup its name @@ -157,41 +154,43 @@ void CSMImporter::InternReadFile( const std::string& pFile, aiNodeAnim* nda = anims_temp.back(); char* ot = nda->mNodeName.data; - while (!IsSpaceOrNewLine(*buffer)) + while (!IsSpaceOrNewLine(*buffer)) { *ot++ = *buffer++; + } *ot = '\0'; nda->mNodeName.length = static_cast(ot-nda->mNodeName.data); } anim->mNumChannels = static_cast(anims_temp.size()); - if (!anim->mNumChannels) + if (!anim->mNumChannels) { throw DeadlyImportError("CSM: Empty $order section"); + } // copy over to the output animation anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; ::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels); - } - else if (TokenMatchI(buffer,"points",6)) { - if (!anim->mNumChannels) + } else if (TokenMatchI(buffer,"points",6)) { + if (!anim->mNumChannels) { throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'"); + } // If we know how many frames we'll read, we can preallocate some storage unsigned int alloc = 100; - if (last != 0x00ffffff) - { + if (last != 0x00ffffff) { alloc = last-first; alloc += alloc>>2u; // + 25% - for (unsigned int i = 0; i < anim->mNumChannels;++i) + for (unsigned int i = 0; i < anim->mNumChannels; ++i) { anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc]; + } } unsigned int filled = 0; // Now read all point data. while (true) { - SkipSpaces(&buffer); - if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$')) { + SkipSpaces(&buffer, end); + if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer, end) || *buffer == '$')) { break; // next section } @@ -202,8 +201,8 @@ void CSMImporter::InternReadFile( const std::string& pFile, for (unsigned int i = 0; i < anim->mNumChannels;++i) { aiNodeAnim* s = anim->mChannels[i]; - if (s->mNumPositionKeys == alloc) { /* need to reallocate? */ - + if (s->mNumPositionKeys == alloc) { + // need to reallocate? aiVectorKey* old = s->mPositionKeys; s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2]; ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc); @@ -211,24 +210,26 @@ void CSMImporter::InternReadFile( const std::string& pFile, } // read x,y,z - if(!SkipSpacesAndLineEnd(&buffer)) + if (!SkipSpacesAndLineEnd(&buffer, end)) { throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample x coord"); + } if (TokenMatchI(buffer, "DROPOUT", 7)) { // seems this is invalid marker data; at least the doc says it's possible ASSIMP_LOG_WARN("CSM: Encountered invalid marker data (DROPOUT)"); - } - else { + } else { aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys; sub->mTime = (double)frame; buffer = fast_atoreal_move(buffer, (float&)sub->mValue.x); - if(!SkipSpacesAndLineEnd(&buffer)) + if (!SkipSpacesAndLineEnd(&buffer, end)) { throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord"); + } buffer = fast_atoreal_move(buffer, (float&)sub->mValue.y); - if(!SkipSpacesAndLineEnd(&buffer)) + if (!SkipSpacesAndLineEnd(&buffer, end)) { throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord"); + } buffer = fast_atoreal_move(buffer, (float&)sub->mValue.z); ++s->mNumPositionKeys; @@ -236,22 +237,22 @@ void CSMImporter::InternReadFile( const std::string& pFile, } // update allocation granularity - if (filled == alloc) + if (filled == alloc) { alloc *= 2; + } ++filled; } // all channels must be complete in order to continue safely. for (unsigned int i = 0; i < anim->mNumChannels;++i) { - - if (!anim->mChannels[i]->mNumPositionKeys) + if (!anim->mChannels[i]->mNumPositionKeys) { throw DeadlyImportError("CSM: Invalid marker track"); + } } } - } - else { + } else { // advance to the next line - SkipLine(&buffer); + SkipLine(&buffer, end); } } @@ -265,7 +266,7 @@ void CSMImporter::InternReadFile( const std::string& pFile, pScene->mRootNode->mNumChildren = anim->mNumChannels; pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels]; - for (unsigned int i = 0; i < anim->mNumChannels;++i) { + for (unsigned int i = 0; i < anim->mNumChannels;++i) { aiNodeAnim* na = anim->mChannels[i]; aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode(); diff --git a/code/AssetLib/CSM/CSMLoader.h b/code/AssetLib/CSM/CSMLoader.h index fc9017d17..2bad73717 100644 --- a/code/AssetLib/CSM/CSMLoader.h +++ b/code/AssetLib/CSM/CSMLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Collada/ColladaExporter.cpp b/code/AssetLib/Collada/ColladaExporter.cpp index 29b714bd7..3fc3a6e15 100644 --- a/code/AssetLib/Collada/ColladaExporter.cpp +++ b/code/AssetLib/Collada/ColladaExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Collada/ColladaExporter.h b/code/AssetLib/Collada/ColladaExporter.h index e372a5c5c..05e076034 100644 --- a/code/AssetLib/Collada/ColladaExporter.h +++ b/code/AssetLib/Collada/ColladaExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Collada/ColladaHelper.cpp b/code/AssetLib/Collada/ColladaHelper.cpp index 0fb172fbb..b5de70624 100644 --- a/code/AssetLib/Collada/ColladaHelper.cpp +++ b/code/AssetLib/Collada/ColladaHelper.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Collada/ColladaHelper.h b/code/AssetLib/Collada/ColladaHelper.h index c5b6a2d13..6662d7354 100644 --- a/code/AssetLib/Collada/ColladaHelper.h +++ b/code/AssetLib/Collada/ColladaHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Collada/ColladaLoader.cpp b/code/AssetLib/Collada/ColladaLoader.cpp index 41e529de0..2574fd2ea 100644 --- a/code/AssetLib/Collada/ColladaLoader.cpp +++ b/code/AssetLib/Collada/ColladaLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -247,7 +247,9 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad // add children. first the *real* ones node->mNumChildren = static_cast(pNode->mChildren.size() + instances.size()); - node->mChildren = new aiNode *[node->mNumChildren]; + if (node->mNumChildren != 0) { + node->mChildren = new aiNode * [node->mNumChildren]; + } for (size_t a = 0; a < pNode->mChildren.size(); ++a) { node->mChildren[a] = BuildHierarchy(pParser, pNode->mChildren[a]); diff --git a/code/AssetLib/Collada/ColladaLoader.h b/code/AssetLib/Collada/ColladaLoader.h index 3cea7f531..0603d419c 100644 --- a/code/AssetLib/Collada/ColladaLoader.h +++ b/code/AssetLib/Collada/ColladaLoader.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Collada/ColladaParser.cpp b/code/AssetLib/Collada/ColladaParser.cpp index 42a8d6052..e7f91b5fe 100644 --- a/code/AssetLib/Collada/ColladaParser.cpp +++ b/code/AssetLib/Collada/ColladaParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -635,7 +635,8 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle const std::string ¤tName = currentNode.name(); if (currentName == "morph") { controller.mType = Morph; - controller.mMeshId = currentNode.attribute("source").as_string(); + std::string id = currentNode.attribute("source").as_string(); + controller.mMeshId = id.substr(1, id.size() - 1); int methodIndex = currentNode.attribute("method").as_int(); if (methodIndex > 0) { std::string method; @@ -654,12 +655,13 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle std::string v; XmlParser::getValueAsString(currentNode, v); const char *content = v.c_str(); + const char *end = content + v.size(); for (unsigned int a = 0; a < 16; a++) { - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); // read a number content = fast_atoreal_move(content, controller.mBindShapeMatrix[a]); // skip whitespace after it - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); } } else if (currentName == "source") { ReadSource(currentNode); @@ -740,7 +742,9 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in data element"); } } else if (currentName == "vcount" && vertexCount > 0) { - const char *text = currentNode.text().as_string(); + const std::string stdText = currentNode.text().as_string(); + const char *text = stdText.c_str(); + const char *end = text + stdText.size(); size_t numWeights = 0; for (std::vector::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) { if (*text == 0) { @@ -749,7 +753,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC *it = strtoul10(text, &text); numWeights += *it; - SkipSpacesAndLineEnd(&text); + SkipSpacesAndLineEnd(&text, end); } // reserve weight count pController.mWeights.resize(numWeights); @@ -758,18 +762,19 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC std::string stdText; XmlParser::getValueAsString(currentNode, stdText); const char *text = stdText.c_str(); + const char *end = text + stdText.size(); for (std::vector>::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) { if (text == nullptr) { throw DeadlyImportError("Out of data while reading "); } - SkipSpacesAndLineEnd(&text); + SkipSpacesAndLineEnd(&text, end); it->first = strtoul10(text, &text); - SkipSpacesAndLineEnd(&text); + SkipSpacesAndLineEnd(&text, end); if (*text == 0) { throw DeadlyImportError("Out of data while reading "); } it->second = strtoul10(text, &text); - SkipSpacesAndLineEnd(&text); + SkipSpacesAndLineEnd(&text, end); } } } @@ -952,15 +957,16 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) { std::string v; XmlParser::getValueAsString(currentNode, v); const char *content = v.c_str(); + const char *end = content + v.size(); content = fast_atoreal_move(content, (ai_real &)pLight.mColor.r); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); content = fast_atoreal_move(content, (ai_real &)pLight.mColor.g); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); content = fast_atoreal_move(content, (ai_real &)pLight.mColor.b); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); } else if (currentName == "constant_attenuation") { XmlParser::getValueAsFloat(currentNode, pLight.mAttConstant); } else if (currentName == "linear_attenuation") { @@ -1220,18 +1226,19 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p std::string v; XmlParser::getValueAsString(currentNode, v); const char *content = v.c_str(); + const char *end = v.c_str() + v.size() + 1; content = fast_atoreal_move(content, (ai_real &)pColor.r); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); content = fast_atoreal_move(content, (ai_real &)pColor.g); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); content = fast_atoreal_move(content, (ai_real &)pColor.b); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); content = fast_atoreal_move(content, (ai_real &)pColor.a); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); } else if (currentName == "texture") { // get name of source texture/sampler XmlParser::getStdStrAttribute(currentNode, "texture", pSampler.mName); @@ -1345,6 +1352,7 @@ void ColladaParser::ReadGeometry(XmlNode &node, Collada::Mesh &pMesh) { if (node.empty()) { return; } + for (XmlNode ¤tNode : node.children()) { const std::string ¤tName = currentNode.name(); if (currentName == "mesh") { @@ -1415,6 +1423,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) { XmlParser::getValueAsString(node, v); v = ai_trim(v); const char *content = v.c_str(); + const char *end = content + v.size(); // read values and store inside an array in the data library mDataLibrary[id] = Data(); @@ -1433,11 +1442,13 @@ void ColladaParser::ReadDataArray(XmlNode &node) { } s.clear(); - while (!IsSpaceOrNewLine(*content)) - s += *content++; + while (!IsSpaceOrNewLine(*content)) { + s += *content; + content++; + } data.mStrings.push_back(s); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); } } else { data.mValues.reserve(count); @@ -1452,7 +1463,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) { content = fast_atoreal_move(content, value); data.mValues.push_back(value); // skip whitespace after it - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); } } } @@ -1617,8 +1628,10 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) { std::string v; XmlParser::getValueAsString(currentNode, v); const char *content = v.c_str(); + const char *end = content + v.size(); + vcount.reserve(numPrimitives); - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); for (unsigned int a = 0; a < numPrimitives; a++) { if (*content == 0) { throw DeadlyImportError("Expected more values while reading contents."); @@ -1626,7 +1639,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) { // read a number vcount.push_back((size_t)strtoul10(content, &content)); // skip whitespace after it - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); } } } @@ -1735,14 +1748,16 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vectormData) { acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource); + const size_t dataSize = acc->mOffset + acc->mCount * acc->mStride; + if (dataSize > acc->mData->mValues.size()) { + throw DeadlyImportError("Not enough data for accessor"); + } } } // and the same for the per-index channels @@ -1796,13 +1815,19 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vectormData) { acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource); + const size_t dataSize = acc->mOffset + acc->mCount * acc->mStride; + if (dataSize > acc->mData->mValues.size()) { + throw DeadlyImportError("Not enough data for accessor"); + } } } // For continued primitives, the given count does not come all in one

, but only one primitive per

size_t numPrimitives = pNumPrimitives; - if (pPrimType == Prim_TriFans || pPrimType == Prim_Polygon) + if (pPrimType == Prim_TriFans || pPrimType == Prim_Polygon) { numPrimitives = 1; + } + // For continued primitives, the given count is actually the number of

's inside the parent tag if (pPrimType == Prim_TriStrips) { size_t numberOfVertices = indices.size() / numOffsets; @@ -2166,15 +2191,15 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform } // how many parameters to read per transformation type - static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 }; + static constexpr unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 }; std::string value; XmlParser::getValueAsString(node, value); const char *content = value.c_str(); - + const char *end = value.c_str() + value.size(); // read as many parameters and store in the transformation for (unsigned int a = 0; a < sNumParameters[pType]; a++) { // skip whitespace before the number - SkipSpacesAndLineEnd(&content); + SkipSpacesAndLineEnd(&content, end); // read a number content = fast_atoreal_move(content, tf.f[a]); } @@ -2268,9 +2293,9 @@ void ColladaParser::ReadNodeGeometry(XmlNode &node, Node *pNode) { urlMat++; s.mMatName = urlMat; + ReadMaterialVertexInputBinding(instanceMatNode, s); // store the association instance.mMaterials[group] = s; - ReadMaterialVertexInputBinding(instanceMatNode, s); } } } diff --git a/code/AssetLib/Collada/ColladaParser.h b/code/AssetLib/Collada/ColladaParser.h index 15982934f..d428ad674 100644 --- a/code/AssetLib/Collada/ColladaParser.h +++ b/code/AssetLib/Collada/ColladaParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- - Copyright (c) 2006-2022, assimp team + Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/DXF/DXFHelper.h b/code/AssetLib/DXF/DXFHelper.h index 4d7893cc4..0bbecdc9e 100644 --- a/code/AssetLib/DXF/DXFHelper.h +++ b/code/AssetLib/DXF/DXFHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/DXF/DXFLoader.cpp b/code/AssetLib/DXF/DXFLoader.cpp index f69cdfce2..0f3da2626 100644 --- a/code/AssetLib/DXF/DXFLoader.cpp +++ b/code/AssetLib/DXF/DXFLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the DXF importer class */ - #ifndef ASSIMP_BUILD_NO_DXF_IMPORTER #include "AssetLib/DXF/DXFLoader.h" @@ -68,25 +67,267 @@ static constexpr size_t AI_DXF_BINARY_IDENT_LEN = sizeof AI_DXF_BINARY_IDENT; // default vertex color that all uncolored vertices will receive static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); -// color indices for DXF - 16 are supported, the table is -// taken directly from the DXF spec. -static const aiColor4D g_aclrDxfIndexColors[] = { - aiColor4D(0.6f, 0.6f, 0.6f, 1.0f), - aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red - aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green - aiColor4D (0.0f, 0.0f, 1.0f, 1.0f), // blue - aiColor4D (0.3f, 1.0f, 0.3f, 1.0f), // light green - aiColor4D (0.3f, 0.3f, 1.0f, 1.0f), // light blue - aiColor4D (1.0f, 0.3f, 0.3f, 1.0f), // light red - aiColor4D (1.0f, 0.0f, 1.0f, 1.0f), // pink - aiColor4D (1.0f, 0.6f, 0.0f, 1.0f), // orange - aiColor4D (0.6f, 0.3f, 0.0f, 1.0f), // dark orange - aiColor4D (1.0f, 1.0f, 0.0f, 1.0f), // yellow - aiColor4D (0.3f, 0.3f, 0.3f, 1.0f), // dark gray - aiColor4D (0.8f, 0.8f, 0.8f, 1.0f), // light gray - aiColor4D (0.0f, 00.f, 0.0f, 1.0f), // black - aiColor4D (1.0f, 1.0f, 1.0f, 1.0f), // white - aiColor4D (0.6f, 0.0f, 1.0f, 1.0f) // violet +// color indices for DXF - 256 are supported, the table is +// taken directly from the AutoCad Index (ACI) table +// https://gohtx.com/acadcolors.php +//STH 2024-0126 +static const aiColor4D g_aclrDxfIndexColors[256] = { + aiColor4D (0.0f, 0.0f ,0.0f, 1.0f), //dxf color code 0 + aiColor4D (1.0f, 0.0f ,0.0f, 1.0f), //dxf color code 1 + aiColor4D (1.0f, 1.0f ,0.0f, 1.0f), //dxf color code 2 + aiColor4D (0.0f, 1.0f ,0.0f, 1.0f), //dxf color code 3 + aiColor4D (0.0f, 1.0f ,1.0f, 1.0f), //dxf color code 4 + aiColor4D (0.0f, 0.0f ,1.0f, 1.0f), //dxf color code 5 + aiColor4D (1.0f, 0.0f ,1.0f, 1.0f), //dxf color code 6 + aiColor4D (1.0f, 1.0f ,1.0f, 1.0f), //dxf color code 7 + aiColor4D (0.3f, 0.3f ,0.3f, 1.0f), //dxf color code 8 + aiColor4D (0.5f, 0.5f ,0.5f, 1.0f), //dxf color code 9 + aiColor4D (1.0f, 0.0f ,0.0f, 1.0f), //dxf color code 10 + aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 11 + aiColor4D (0.7f, 0.0f ,0.0f, 1.0f), //dxf color code 12 + aiColor4D (0.7f, 0.5f ,0.5f, 1.0f), //dxf color code 13 + aiColor4D (0.5f, 0.0f ,0.0f, 1.0f), //dxf color code 14 + aiColor4D (0.5f, 0.3f ,0.3f, 1.0f), //dxf color code 15 + aiColor4D (0.4f, 0.0f ,0.0f, 1.0f), //dxf color code 16 + aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 17 + aiColor4D (0.3f, 0.0f ,0.0f, 1.0f), //dxf color code 18 + aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 19 + aiColor4D (1.0f, 0.2f ,0.0f, 1.0f), //dxf color code 20 + aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 21 + aiColor4D (0.7f, 0.2f ,0.0f, 1.0f), //dxf color code 22 + aiColor4D (0.7f, 0.6f ,0.5f, 1.0f), //dxf color code 23 + aiColor4D (0.5f, 0.1f ,0.0f, 1.0f), //dxf color code 24 + aiColor4D (0.5f, 0.4f ,0.3f, 1.0f), //dxf color code 25 + aiColor4D (0.4f, 0.1f ,0.0f, 1.0f), //dxf color code 26 + aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 27 + aiColor4D (0.3f, 0.1f ,0.0f, 1.0f), //dxf color code 28 + aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 29 + aiColor4D (1.0f, 0.5f ,0.0f, 1.0f), //dxf color code 30 + aiColor4D (1.0f, 0.8f ,0.7f, 1.0f), //dxf color code 31 + aiColor4D (0.7f, 0.4f ,0.0f, 1.0f), //dxf color code 32 + aiColor4D (0.7f, 0.6f ,0.5f, 1.0f), //dxf color code 33 + aiColor4D (0.5f, 0.3f ,0.0f, 1.0f), //dxf color code 34 + aiColor4D (0.5f, 0.4f ,0.3f, 1.0f), //dxf color code 35 + aiColor4D (0.4f, 0.2f ,0.0f, 1.0f), //dxf color code 36 + aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 37 + aiColor4D (0.3f, 0.2f ,0.0f, 1.0f), //dxf color code 38 + aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 39 + aiColor4D (1.0f, 0.7f ,0.0f, 1.0f), //dxf color code 40 + aiColor4D (1.0f, 0.9f ,0.7f, 1.0f), //dxf color code 41 + aiColor4D (0.7f, 0.6f ,0.0f, 1.0f), //dxf color code 42 + aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 43 + aiColor4D (0.5f, 0.4f ,0.0f, 1.0f), //dxf color code 44 + aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 45 + aiColor4D (0.4f, 0.3f ,0.0f, 1.0f), //dxf color code 46 + aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 47 + aiColor4D (0.3f, 0.2f ,0.0f, 1.0f), //dxf color code 48 + aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 49 + aiColor4D (1.0f, 1.0f ,0.0f, 1.0f), //dxf color code 50 + aiColor4D (1.0f, 1.0f ,0.7f, 1.0f), //dxf color code 51 + aiColor4D (0.7f, 0.7f ,0.0f, 1.0f), //dxf color code 52 + aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 53 + aiColor4D (0.5f, 0.5f ,0.0f, 1.0f), //dxf color code 54 + aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 55 + aiColor4D (0.4f, 0.4f ,0.0f, 1.0f), //dxf color code 56 + aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 57 + aiColor4D (0.3f, 0.3f ,0.0f, 1.0f), //dxf color code 58 + aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 59 + aiColor4D (0.7f, 1.0f ,0.0f, 1.0f), //dxf color code 60 + aiColor4D (0.9f, 1.0f ,0.7f, 1.0f), //dxf color code 61 + aiColor4D (0.6f, 0.7f ,0.0f, 1.0f), //dxf color code 62 + aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 63 + aiColor4D (0.4f, 0.5f ,0.0f, 1.0f), //dxf color code 64 + aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 65 + aiColor4D (0.3f, 0.4f ,0.0f, 1.0f), //dxf color code 66 + aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 67 + aiColor4D (0.2f, 0.3f ,0.0f, 1.0f), //dxf color code 68 + aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 69 + aiColor4D (0.5f, 1.0f ,0.0f, 1.0f), //dxf color code 70 + aiColor4D (0.8f, 1.0f ,0.7f, 1.0f), //dxf color code 71 + aiColor4D (0.4f, 0.7f ,0.0f, 1.0f), //dxf color code 72 + aiColor4D (0.6f, 0.7f ,0.5f, 1.0f), //dxf color code 73 + aiColor4D (0.3f, 0.5f ,0.0f, 1.0f), //dxf color code 74 + aiColor4D (0.4f, 0.5f ,0.3f, 1.0f), //dxf color code 75 + aiColor4D (0.2f, 0.4f ,0.0f, 1.0f), //dxf color code 76 + aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 77 + aiColor4D (0.2f, 0.3f ,0.0f, 1.0f), //dxf color code 78 + aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 79 + aiColor4D (0.2f, 1.0f ,0.0f, 1.0f), //dxf color code 80 + aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 81 + aiColor4D (0.2f, 0.7f ,0.0f, 1.0f), //dxf color code 82 + aiColor4D (0.6f, 0.7f ,0.5f, 1.0f), //dxf color code 83 + aiColor4D (0.1f, 0.5f ,0.0f, 1.0f), //dxf color code 84 + aiColor4D (0.4f, 0.5f ,0.3f, 1.0f), //dxf color code 85 + aiColor4D (0.1f, 0.4f ,0.0f, 1.0f), //dxf color code 86 + aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 87 + aiColor4D (0.1f, 0.3f ,0.0f, 1.0f), //dxf color code 88 + aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 89 + aiColor4D (0.0f, 1.0f ,0.0f, 1.0f), //dxf color code 90 + aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 91 + aiColor4D (0.0f, 0.7f ,0.0f, 1.0f), //dxf color code 92 + aiColor4D (0.5f, 0.7f ,0.5f, 1.0f), //dxf color code 93 + aiColor4D (0.0f, 0.5f ,0.0f, 1.0f), //dxf color code 94 + aiColor4D (0.3f, 0.5f ,0.3f, 1.0f), //dxf color code 95 + aiColor4D (0.0f, 0.4f ,0.0f, 1.0f), //dxf color code 96 + aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 97 + aiColor4D (0.0f, 0.3f ,0.0f, 1.0f), //dxf color code 98 + aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 99 + aiColor4D (0.0f, 1.0f ,0.2f, 1.0f), //dxf color code 100 + aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 101 + aiColor4D (0.0f, 0.7f ,0.2f, 1.0f), //dxf color code 102 + aiColor4D (0.5f, 0.7f ,0.6f, 1.0f), //dxf color code 103 + aiColor4D (0.0f, 0.5f ,0.1f, 1.0f), //dxf color code 104 + aiColor4D (0.3f, 0.5f ,0.4f, 1.0f), //dxf color code 105 + aiColor4D (0.0f, 0.4f ,0.1f, 1.0f), //dxf color code 106 + aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 107 + aiColor4D (0.0f, 0.3f ,0.1f, 1.0f), //dxf color code 108 + aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 109 + aiColor4D (0.0f, 1.0f ,0.5f, 1.0f), //dxf color code 110 + aiColor4D (0.7f, 1.0f ,0.8f, 1.0f), //dxf color code 111 + aiColor4D (0.0f, 0.7f ,0.4f, 1.0f), //dxf color code 112 + aiColor4D (0.5f, 0.7f ,0.6f, 1.0f), //dxf color code 113 + aiColor4D (0.0f, 0.5f ,0.3f, 1.0f), //dxf color code 114 + aiColor4D (0.3f, 0.5f ,0.4f, 1.0f), //dxf color code 115 + aiColor4D (0.0f, 0.4f ,0.2f, 1.0f), //dxf color code 116 + aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 117 + aiColor4D (0.0f, 0.3f ,0.2f, 1.0f), //dxf color code 118 + aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 119 + aiColor4D (0.0f, 1.0f ,0.7f, 1.0f), //dxf color code 120 + aiColor4D (0.7f, 1.0f ,0.9f, 1.0f), //dxf color code 121 + aiColor4D (0.0f, 0.7f ,0.6f, 1.0f), //dxf color code 122 + aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 123 + aiColor4D (0.0f, 0.5f ,0.4f, 1.0f), //dxf color code 124 + aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 125 + aiColor4D (0.0f, 0.4f ,0.3f, 1.0f), //dxf color code 126 + aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 127 + aiColor4D (0.0f, 0.3f ,0.2f, 1.0f), //dxf color code 128 + aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 129 + aiColor4D (0.0f, 1.0f ,1.0f, 1.0f), //dxf color code 130 + aiColor4D (0.7f, 1.0f ,1.0f, 1.0f), //dxf color code 131 + aiColor4D (0.0f, 0.7f ,0.7f, 1.0f), //dxf color code 132 + aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 133 + aiColor4D (0.0f, 0.5f ,0.5f, 1.0f), //dxf color code 134 + aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 135 + aiColor4D (0.0f, 0.4f ,0.4f, 1.0f), //dxf color code 136 + aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 137 + aiColor4D (0.0f, 0.3f ,0.3f, 1.0f), //dxf color code 138 + aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 139 + aiColor4D (0.0f, 0.7f ,1.0f, 1.0f), //dxf color code 140 + aiColor4D (0.7f, 0.9f ,1.0f, 1.0f), //dxf color code 141 + aiColor4D (0.0f, 0.6f ,0.7f, 1.0f), //dxf color code 142 + aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 143 + aiColor4D (0.0f, 0.4f ,0.5f, 1.0f), //dxf color code 144 + aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 145 + aiColor4D (0.0f, 0.3f ,0.4f, 1.0f), //dxf color code 146 + aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 147 + aiColor4D (0.0f, 0.2f ,0.3f, 1.0f), //dxf color code 148 + aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 149 + aiColor4D (0.0f, 0.5f ,1.0f, 1.0f), //dxf color code 150 + aiColor4D (0.7f, 0.8f ,1.0f, 1.0f), //dxf color code 151 + aiColor4D (0.0f, 0.4f ,0.7f, 1.0f), //dxf color code 152 + aiColor4D (0.5f, 0.6f ,0.7f, 1.0f), //dxf color code 153 + aiColor4D (0.0f, 0.3f ,0.5f, 1.0f), //dxf color code 154 + aiColor4D (0.3f, 0.4f ,0.5f, 1.0f), //dxf color code 155 + aiColor4D (0.0f, 0.2f ,0.4f, 1.0f), //dxf color code 156 + aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 157 + aiColor4D (0.0f, 0.2f ,0.3f, 1.0f), //dxf color code 158 + aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 159 + aiColor4D (0.0f, 0.2f ,1.0f, 1.0f), //dxf color code 160 + aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 161 + aiColor4D (0.0f, 0.2f ,0.7f, 1.0f), //dxf color code 162 + aiColor4D (0.5f, 0.6f ,0.7f, 1.0f), //dxf color code 163 + aiColor4D (0.0f, 0.1f ,0.5f, 1.0f), //dxf color code 164 + aiColor4D (0.3f, 0.4f ,0.5f, 1.0f), //dxf color code 165 + aiColor4D (0.0f, 0.1f ,0.4f, 1.0f), //dxf color code 166 + aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 167 + aiColor4D (0.0f, 0.1f ,0.3f, 1.0f), //dxf color code 168 + aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 169 + aiColor4D (0.0f, 0.0f ,1.0f, 1.0f), //dxf color code 170 + aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 171 + aiColor4D (0.0f, 0.0f ,0.7f, 1.0f), //dxf color code 172 + aiColor4D (0.5f, 0.5f ,0.7f, 1.0f), //dxf color code 173 + aiColor4D (0.0f, 0.0f ,0.5f, 1.0f), //dxf color code 174 + aiColor4D (0.3f, 0.3f ,0.5f, 1.0f), //dxf color code 175 + aiColor4D (0.0f, 0.0f ,0.4f, 1.0f), //dxf color code 176 + aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 177 + aiColor4D (0.0f, 0.0f ,0.3f, 1.0f), //dxf color code 178 + aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 179 + aiColor4D (0.2f, 0.0f ,1.0f, 1.0f), //dxf color code 180 + aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 181 + aiColor4D (0.2f, 0.0f ,0.7f, 1.0f), //dxf color code 182 + aiColor4D (0.6f, 0.5f ,0.7f, 1.0f), //dxf color code 183 + aiColor4D (0.1f, 0.0f ,0.5f, 1.0f), //dxf color code 184 + aiColor4D (0.4f, 0.3f ,0.5f, 1.0f), //dxf color code 185 + aiColor4D (0.1f, 0.0f ,0.4f, 1.0f), //dxf color code 186 + aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 187 + aiColor4D (0.1f, 0.0f ,0.3f, 1.0f), //dxf color code 188 + aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 189 + aiColor4D (0.5f, 0.0f ,1.0f, 1.0f), //dxf color code 190 + aiColor4D (0.8f, 0.7f ,1.0f, 1.0f), //dxf color code 191 + aiColor4D (0.4f, 0.0f ,0.7f, 1.0f), //dxf color code 192 + aiColor4D (0.6f, 0.5f ,0.7f, 1.0f), //dxf color code 193 + aiColor4D (0.3f, 0.0f ,0.5f, 1.0f), //dxf color code 194 + aiColor4D (0.4f, 0.3f ,0.5f, 1.0f), //dxf color code 195 + aiColor4D (0.2f, 0.0f ,0.4f, 1.0f), //dxf color code 196 + aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 197 + aiColor4D (0.2f, 0.0f ,0.3f, 1.0f), //dxf color code 198 + aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 199 + aiColor4D (0.7f, 0.0f ,1.0f, 1.0f), //dxf color code 200 + aiColor4D (0.9f, 0.7f ,1.0f, 1.0f), //dxf color code 201 + aiColor4D (0.6f, 0.0f ,0.7f, 1.0f), //dxf color code 202 + aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 203 + aiColor4D (0.4f, 0.0f ,0.5f, 1.0f), //dxf color code 204 + aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 205 + aiColor4D (0.3f, 0.0f ,0.4f, 1.0f), //dxf color code 206 + aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 207 + aiColor4D (0.2f, 0.0f ,0.3f, 1.0f), //dxf color code 208 + aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 209 + aiColor4D (1.0f, 0.0f ,1.0f, 1.0f), //dxf color code 210 + aiColor4D (1.0f, 0.7f ,1.0f, 1.0f), //dxf color code 211 + aiColor4D (0.7f, 0.0f ,0.7f, 1.0f), //dxf color code 212 + aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 213 + aiColor4D (0.5f, 0.0f ,0.5f, 1.0f), //dxf color code 214 + aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 215 + aiColor4D (0.4f, 0.0f ,0.4f, 1.0f), //dxf color code 216 + aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 217 + aiColor4D (0.3f, 0.0f ,0.3f, 1.0f), //dxf color code 218 + aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 219 + aiColor4D (1.0f, 0.0f ,0.7f, 1.0f), //dxf color code 220 + aiColor4D (1.0f, 0.7f ,0.9f, 1.0f), //dxf color code 221 + aiColor4D (0.7f, 0.0f ,0.6f, 1.0f), //dxf color code 222 + aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 223 + aiColor4D (0.5f, 0.0f ,0.4f, 1.0f), //dxf color code 224 + aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 225 + aiColor4D (0.4f, 0.0f ,0.3f, 1.0f), //dxf color code 226 + aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 227 + aiColor4D (0.3f, 0.0f ,0.2f, 1.0f), //dxf color code 228 + aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 229 + aiColor4D (1.0f, 0.0f ,0.5f, 1.0f), //dxf color code 230 + aiColor4D (1.0f, 0.7f ,0.8f, 1.0f), //dxf color code 231 + aiColor4D (0.7f, 0.0f ,0.4f, 1.0f), //dxf color code 232 + aiColor4D (0.7f, 0.5f ,0.6f, 1.0f), //dxf color code 233 + aiColor4D (0.5f, 0.0f ,0.3f, 1.0f), //dxf color code 234 + aiColor4D (0.5f, 0.3f ,0.4f, 1.0f), //dxf color code 235 + aiColor4D (0.4f, 0.0f ,0.2f, 1.0f), //dxf color code 236 + aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 237 + aiColor4D (0.3f, 0.0f ,0.2f, 1.0f), //dxf color code 238 + aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 239 + aiColor4D (1.0f, 0.0f ,0.2f, 1.0f), //dxf color code 240 + aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 241 + aiColor4D (0.7f, 0.0f ,0.2f, 1.0f), //dxf color code 242 + aiColor4D (0.7f, 0.5f ,0.6f, 1.0f), //dxf color code 243 + aiColor4D (0.5f, 0.0f ,0.1f, 1.0f), //dxf color code 244 + aiColor4D (0.5f, 0.3f ,0.4f, 1.0f), //dxf color code 245 + aiColor4D (0.4f, 0.0f ,0.1f, 1.0f), //dxf color code 246 + aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 247 + aiColor4D (0.3f, 0.0f ,0.1f, 1.0f), //dxf color code 248 + aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 249 + aiColor4D (0.2f, 0.2f ,0.2f, 1.0f), //dxf color code 250 + aiColor4D (0.3f, 0.3f ,0.3f, 1.0f), //dxf color code 251 + aiColor4D (0.4f, 0.4f ,0.4f, 1.0f), //dxf color code 252 + aiColor4D (0.5f, 0.5f ,0.5f, 1.0f), //dxf color code 253 + aiColor4D (0.7f, 0.7f ,0.7f, 1.0f), //dxf color code 254 + aiColor4D (1.0f, 1.0f ,1.0f, 1.0f) //dxf color code 255 }; #define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0])) @@ -372,8 +613,12 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc // XXX order aiMatrix4x4 trafo, tmp; aiMatrix4x4::Translation(-bl_src.base,trafo); - trafo *= aiMatrix4x4::Scaling(insert.scale,tmp); + //Need to translate position before scaling the insert + //otherwise the position ends up being the position*scaling + //STH 2024.01.17 trafo *= aiMatrix4x4::Translation(insert.pos,tmp); + trafo *= aiMatrix4x4::Scaling(insert.scale,tmp); + //trafo *= aiMatrix4x4::Translation(insert.pos,tmp); // XXX rotation currently ignored - I didn't find an appropriate sample model. if (insert.angle != 0.f) { diff --git a/code/AssetLib/DXF/DXFLoader.h b/code/AssetLib/DXF/DXFLoader.h index 89a0b79c2..9230bccbd 100644 --- a/code/AssetLib/DXF/DXFLoader.h +++ b/code/AssetLib/DXF/DXFLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXAnimation.cpp b/code/AssetLib/FBX/FBXAnimation.cpp index af92ebe51..fdde37f24 100644 --- a/code/AssetLib/FBX/FBXAnimation.cpp +++ b/code/AssetLib/FBX/FBXAnimation.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp index 55424a6a8..b828090e5 100644 --- a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp +++ b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXCommon.h b/code/AssetLib/FBX/FBXCommon.h index c3d715892..7e0fb2553 100644 --- a/code/AssetLib/FBX/FBXCommon.h +++ b/code/AssetLib/FBX/FBXCommon.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXCompileConfig.h b/code/AssetLib/FBX/FBXCompileConfig.h index 927a3c5f6..9885ca346 100644 --- a/code/AssetLib/FBX/FBXCompileConfig.h +++ b/code/AssetLib/FBX/FBXCompileConfig.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 62ada774f..234931cbe 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -76,6 +76,53 @@ using namespace Util; #define CONVERT_FBX_TIME(time) static_cast(time) / 46186158000LL +static void correctRootTransform(const aiScene *scene) { + if (scene == nullptr) { + return; + } + + if (scene->mMetaData == nullptr) { + return; + } + + int32_t UpAxis = 1, UpAxisSign = 1, FrontAxis = 2, FrontAxisSign = 1, CoordAxis = 0, CoordAxisSign = 1; + double UnitScaleFactor = 1.0; + for (unsigned MetadataIndex = 0; MetadataIndex < scene->mMetaData->mNumProperties; ++MetadataIndex) { + if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UpAxis") == 0) { + scene->mMetaData->Get(MetadataIndex, UpAxis); + } + if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UpAxisSign") == 0) { + scene->mMetaData->Get(MetadataIndex, UpAxisSign); + } + if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "FrontAxis") == 0) { + scene->mMetaData->Get(MetadataIndex, FrontAxis); + } + if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "FrontAxisSign") == 0) { + scene->mMetaData->Get(MetadataIndex, FrontAxisSign); + } + if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "CoordAxis") == 0) { + scene->mMetaData->Get(MetadataIndex, CoordAxis); + } + if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "CoordAxisSign") == 0) { + scene->mMetaData->Get(MetadataIndex, CoordAxisSign); + } + if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UnitScaleFactor") == 0) { + scene->mMetaData->Get(MetadataIndex, UnitScaleFactor); + } + } + + aiVector3D upVec, forwardVec, rightVec; + upVec[UpAxis] = UpAxisSign * static_cast(UnitScaleFactor); + forwardVec[FrontAxis] = FrontAxisSign * static_cast(UnitScaleFactor); + rightVec[CoordAxis] = CoordAxisSign * (float)UnitScaleFactor; + + aiMatrix4x4 mat(rightVec.x, rightVec.y, rightVec.z, 0.0f, + upVec.x, upVec.y, upVec.z, 0.0f, + forwardVec.x, forwardVec.y, forwardVec.z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + scene->mRootNode->mTransformation *= mat; +} + FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) : defaultMaterialIndex(), mMeshes(), @@ -133,6 +180,8 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo // need not contain geometry (i.e. camera animations, raw armatures). if (out->mNumMeshes == 0) { out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; + } else { + correctRootTransform(mSceneOut); } } @@ -1811,7 +1860,7 @@ aiString FBXConverter::GetTexturePath(const Texture *tex) { // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it // This may occur on this case too, it has to be studied path.data[0] = '*'; - path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); + path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index); } } } @@ -2391,7 +2440,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) path.data[0] = '*'; - path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); + path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index); } out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0); @@ -2757,7 +2806,7 @@ void FBXConverter::ProcessMorphAnimDatas(std::map auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo); auto geoIndex = static_cast(std::distance(model->GetGeometry().begin(), geoIt)); auto name = aiString(FixNodeName(model->Name() + "*")); - name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex); + name.length = 1 + ASSIMP_itoa10(name.data + name.length, AI_MAXLEN - 1, geoIndex); morphAnimData *animData; auto animIt = morphAnimDatas->find(name.C_Str()); if (animIt == morphAnimDatas->end()) { @@ -3239,9 +3288,9 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, } if (keyframeLists[TransformationComp_Rotation].size() > 0) { - InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], AI_DEG_TO_RAD(defRotation), maxTime, minTime, rotOrder); + InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder); } else { - aiQuaternion defQuat = EulerToQuaternion(AI_DEG_TO_RAD(defRotation), rotOrder); + aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; outRotations[i].mValue = defQuat; @@ -3263,7 +3312,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, const aiVector3D& preRotation = PropertyGet(props, "PreRotation", ok); if (ok && preRotation.SquareLength() > zero_epsilon) { - const aiQuaternion preQuat = EulerToQuaternion(AI_DEG_TO_RAD(preRotation), Model::RotOrder_EulerXYZ); + const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mValue = preQuat * outRotations[i].mValue; } @@ -3271,7 +3320,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, const aiVector3D& postRotation = PropertyGet(props, "PostRotation", ok); if (ok && postRotation.SquareLength() > zero_epsilon) { - const aiQuaternion postQuat = EulerToQuaternion(AI_DEG_TO_RAD(postRotation), Model::RotOrder_EulerXYZ); + const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mValue = outRotations[i].mValue * postQuat; } diff --git a/code/AssetLib/FBX/FBXConverter.h b/code/AssetLib/FBX/FBXConverter.h index 41acb6ffe..73dc9e5a7 100644 --- a/code/AssetLib/FBX/FBXConverter.h +++ b/code/AssetLib/FBX/FBXConverter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXDeformer.cpp b/code/AssetLib/FBX/FBXDeformer.cpp index 8f944527a..582042360 100644 --- a/code/AssetLib/FBX/FBXDeformer.cpp +++ b/code/AssetLib/FBX/FBXDeformer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index ee4a6632b..3fb0964c4 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index 3af757a19..a103321c0 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXDocumentUtil.cpp b/code/AssetLib/FBX/FBXDocumentUtil.cpp index c41eb2747..64105f351 100644 --- a/code/AssetLib/FBX/FBXDocumentUtil.cpp +++ b/code/AssetLib/FBX/FBXDocumentUtil.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXExportNode.cpp b/code/AssetLib/FBX/FBXExportNode.cpp index 21e591425..ae9586968 100644 --- a/code/AssetLib/FBX/FBXExportNode.cpp +++ b/code/AssetLib/FBX/FBXExportNode.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXExportNode.h b/code/AssetLib/FBX/FBXExportNode.h index 99644b216..7661ab1be 100644 --- a/code/AssetLib/FBX/FBXExportNode.h +++ b/code/AssetLib/FBX/FBXExportNode.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXExportProperty.cpp b/code/AssetLib/FBX/FBXExportProperty.cpp index 3216d7d85..5fbe84fa7 100644 --- a/code/AssetLib/FBX/FBXExportProperty.cpp +++ b/code/AssetLib/FBX/FBXExportProperty.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXExportProperty.h b/code/AssetLib/FBX/FBXExportProperty.h index 26d0cf223..93f8cfbe0 100644 --- a/code/AssetLib/FBX/FBXExportProperty.h +++ b/code/AssetLib/FBX/FBXExportProperty.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXExporter.cpp b/code/AssetLib/FBX/FBXExporter.cpp index 3c6e8fd4d..3b1dd335e 100644 --- a/code/AssetLib/FBX/FBXExporter.cpp +++ b/code/AssetLib/FBX/FBXExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -69,6 +69,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include // RESOURCES: // https://code.blender.org/2013/08/fbx-binary-file-format-specification/ @@ -1050,7 +1051,7 @@ aiNode* get_node_for_mesh(unsigned int meshIndex, aiNode* node) aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) { std::vector node_chain; - while (node != scene->mRootNode) { + while (node != scene->mRootNode && node != nullptr) { node_chain.push_back(node); node = node->mParent; } @@ -1062,7 +1063,7 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) } inline int64_t to_ktime(double ticks, const aiAnimation* anim) { - if (anim->mTicksPerSecond <= 0) { + if (FP_ZERO == std::fpclassify(anim->mTicksPerSecond)) { return static_cast(ticks) * FBX::SECOND; } return (static_cast(ticks / anim->mTicksPerSecond)) * FBX::SECOND; @@ -1088,6 +1089,8 @@ void FBXExporter::WriteObjects () bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true); std::vector> vVertexIndice;//save vertex_indices as it is needed later + const auto bTransparencyFactorReferencedToOpacity = mProperties->GetPropertyBool(AI_CONFIG_EXPORT_FBX_TRANSPARENCY_FACTOR_REFER_TO_OPACITY, false); + // geometry (aiMesh) mesh_uids.clear(); indent = 1; @@ -1444,13 +1447,21 @@ void FBXExporter::WriteObjects () // "TransparentColor" / "TransparencyFactor"... // thanks FBX, for your insightful interpretation of consistency p.AddP70colorA("TransparentColor", c.r, c.g, c.b); - // TransparencyFactor defaults to 0.0, so set it to 1.0. - // note: Maya always sets this to 1.0, - // so we can't use it sensibly as "Opacity". - // In stead we rely on the legacy "Opacity" value, below. - // Blender also relies on "Opacity" not "TransparencyFactor", - // probably for a similar reason. - p.AddP70numberA("TransparencyFactor", 1.0); + + if (!bTransparencyFactorReferencedToOpacity) { + // TransparencyFactor defaults to 0.0, so set it to 1.0. + // note: Maya always sets this to 1.0, + // so we can't use it sensibly as "Opacity". + // In stead we rely on the legacy "Opacity" value, below. + // Blender also relies on "Opacity" not "TransparencyFactor", + // probably for a similar reason. + p.AddP70numberA("TransparencyFactor", 1.0); + } + } + if (bTransparencyFactorReferencedToOpacity) { + if (m->Get(AI_MATKEY_OPACITY, f) == aiReturn_SUCCESS) { + p.AddP70numberA("TransparencyFactor", 1.0 - f); + } } if (m->Get(AI_MATKEY_COLOR_REFLECTIVE, c) == aiReturn_SUCCESS) { p.AddP70colorA("ReflectionColor", c.r, c.g, c.b); @@ -1748,7 +1759,7 @@ void FBXExporter::WriteObjects () int64_t blendshape_uid = generate_uid(); mesh_uids.push_back(blendshape_uid); bsnode.AddProperty(blendshape_uid); - bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Blendshape"); + bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Geometry"); bsnode.AddProperty("Shape"); bsnode.AddChild("Version", int32_t(100)); bsnode.Begin(outstream, binary, indent); @@ -1807,7 +1818,7 @@ void FBXExporter::WriteObjects () p.AddP70numberA("DeformPercent", 0.0); sdnode.AddChild(p); // TODO: Normally just one weight per channel, adding stub for later development - std::vectorfFullWeights; + std::vectorfFullWeights; fFullWeights.push_back(100.); sdnode.AddChild("FullWeights", fFullWeights); sdnode.Dump(outstream, binary, indent); diff --git a/code/AssetLib/FBX/FBXExporter.h b/code/AssetLib/FBX/FBXExporter.h index 659f9368a..df9029196 100644 --- a/code/AssetLib/FBX/FBXExporter.h +++ b/code/AssetLib/FBX/FBXExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXImportSettings.h b/code/AssetLib/FBX/FBXImportSettings.h index 698901180..74290f7e0 100644 --- a/code/AssetLib/FBX/FBXImportSettings.h +++ b/code/AssetLib/FBX/FBXImportSettings.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXImporter.cpp b/code/AssetLib/FBX/FBXImporter.cpp index afd4b11c1..3a8fb8b8a 100644 --- a/code/AssetLib/FBX/FBXImporter.cpp +++ b/code/AssetLib/FBX/FBXImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXImporter.h b/code/AssetLib/FBX/FBXImporter.h index d12b45969..8e8a7db78 100644 --- a/code/AssetLib/FBX/FBXImporter.h +++ b/code/AssetLib/FBX/FBXImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXMaterial.cpp b/code/AssetLib/FBX/FBXMaterial.cpp index bcb9bc42a..3872a4b38 100644 --- a/code/AssetLib/FBX/FBXMaterial.cpp +++ b/code/AssetLib/FBX/FBXMaterial.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXMeshGeometry.cpp b/code/AssetLib/FBX/FBXMeshGeometry.cpp index 8c6499a91..67488f53a 100644 --- a/code/AssetLib/FBX/FBXMeshGeometry.cpp +++ b/code/AssetLib/FBX/FBXMeshGeometry.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -644,10 +644,12 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector& materials_out, cons return; } - // materials are handled separately. First of all, they are assigned per-face - // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect - // has a slightly different meaning for materials. - ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials")); + if (source["Materials"]) { + // materials are handled separately. First of all, they are assigned per-face + // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect + // has a slightly different meaning for materials. + ParseVectorDataArray(materials_out, GetRequiredElement(source, "Materials")); + } if (MappingInformationType == "AllSame") { // easy - same material for all faces diff --git a/code/AssetLib/FBX/FBXMeshGeometry.h b/code/AssetLib/FBX/FBXMeshGeometry.h index 3d67ec567..980d1a334 100644 --- a/code/AssetLib/FBX/FBXMeshGeometry.h +++ b/code/AssetLib/FBX/FBXMeshGeometry.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXModel.cpp b/code/AssetLib/FBX/FBXModel.cpp index d731d2e29..c108dd78b 100644 --- a/code/AssetLib/FBX/FBXModel.cpp +++ b/code/AssetLib/FBX/FBXModel.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXNodeAttribute.cpp b/code/AssetLib/FBX/FBXNodeAttribute.cpp index 34fcdcf77..1e7dfa8c0 100644 --- a/code/AssetLib/FBX/FBXNodeAttribute.cpp +++ b/code/AssetLib/FBX/FBXNodeAttribute.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXParser.cpp b/code/AssetLib/FBX/FBXParser.cpp index 7baa7ed39..d0482e067 100644 --- a/code/AssetLib/FBX/FBXParser.cpp +++ b/code/AssetLib/FBX/FBXParser.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXParser.h b/code/AssetLib/FBX/FBXParser.h index 5f231738d..2ca216d8c 100644 --- a/code/AssetLib/FBX/FBXParser.h +++ b/code/AssetLib/FBX/FBXParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -63,7 +63,6 @@ class Scope; class Parser; class Element; -// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03 using ScopeList = std::vector; using ElementMap = std::fbx_unordered_multimap< std::string, Element*>; using ElementCollection = std::pair; @@ -135,7 +134,7 @@ public: const char* elementNameCStr = elementName.c_str(); for (auto element = elements.begin(); element != elements.end(); ++element) { - if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) { + if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, AI_MAXLEN)) { return element->second; } } diff --git a/code/AssetLib/FBX/FBXProperties.cpp b/code/AssetLib/FBX/FBXProperties.cpp index 1c050617d..6f577d09f 100644 --- a/code/AssetLib/FBX/FBXProperties.cpp +++ b/code/AssetLib/FBX/FBXProperties.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -243,7 +243,6 @@ DirectPropertyMap PropertyTable::GetUnparsedProperties() const // Read the element's value. // Wrap the naked pointer (since the call site is required to acquire ownership) - // std::unique_ptr from C++11 would be preferred both as a wrapper and a return value. std::shared_ptr prop = std::shared_ptr(ReadTypedProperty(*currentElement.second)); // Element could not be read. Skip it. diff --git a/code/AssetLib/FBX/FBXProperties.h b/code/AssetLib/FBX/FBXProperties.h index 18816117a..4799b8056 100644 --- a/code/AssetLib/FBX/FBXProperties.h +++ b/code/AssetLib/FBX/FBXProperties.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXTokenizer.cpp b/code/AssetLib/FBX/FBXTokenizer.cpp index 45d5e7750..007e08d46 100644 --- a/code/AssetLib/FBX/FBXTokenizer.cpp +++ b/code/AssetLib/FBX/FBXTokenizer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXTokenizer.h b/code/AssetLib/FBX/FBXTokenizer.h index 05a0725bd..dedfab66a 100644 --- a/code/AssetLib/FBX/FBXTokenizer.h +++ b/code/AssetLib/FBX/FBXTokenizer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXUtil.cpp b/code/AssetLib/FBX/FBXUtil.cpp index e2903c536..a787a9f1d 100644 --- a/code/AssetLib/FBX/FBXUtil.cpp +++ b/code/AssetLib/FBX/FBXUtil.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/FBX/FBXUtil.h b/code/AssetLib/FBX/FBXUtil.h index 4674a5054..eb9ae14ed 100644 --- a/code/AssetLib/FBX/FBXUtil.h +++ b/code/AssetLib/FBX/FBXUtil.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/HMP/HMPFileData.h b/code/AssetLib/HMP/HMPFileData.h index b297136ba..5f6ca4f55 100644 --- a/code/AssetLib/HMP/HMPFileData.h +++ b/code/AssetLib/HMP/HMPFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -49,7 +49,7 @@ namespace HMP { #include #include -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" #define AI_HMP_MAGIC_NUMBER_BE_4 AI_MAKE_MAGIC("HMP4") #define AI_HMP_MAGIC_NUMBER_LE_4 AI_MAKE_MAGIC("4PMH") diff --git a/code/AssetLib/HMP/HMPLoader.cpp b/code/AssetLib/HMP/HMPLoader.cpp index 5ccb2b474..30931a920 100644 --- a/code/AssetLib/HMP/HMPLoader.cpp +++ b/code/AssetLib/HMP/HMPLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/HMP/HMPLoader.h b/code/AssetLib/HMP/HMPLoader.h index 4d5f5f22f..e665b8d18 100644 --- a/code/AssetLib/HMP/HMPLoader.h +++ b/code/AssetLib/HMP/HMPLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/HMP/HalfLifeFileData.h b/code/AssetLib/HMP/HalfLifeFileData.h index f47862b7a..687b6108c 100644 --- a/code/AssetLib/HMP/HalfLifeFileData.h +++ b/code/AssetLib/HMP/HalfLifeFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/IFC/IFCBoolean.cpp b/code/AssetLib/IFC/IFCBoolean.cpp index f4d53990e..559bd7b2f 100644 --- a/code/AssetLib/IFC/IFCBoolean.cpp +++ b/code/AssetLib/IFC/IFCBoolean.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/IFC/IFCCurve.cpp b/code/AssetLib/IFC/IFCCurve.cpp index 44165befc..847803dfa 100644 --- a/code/AssetLib/IFC/IFCCurve.cpp +++ b/code/AssetLib/IFC/IFCCurve.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/IFC/IFCGeometry.cpp b/code/AssetLib/IFC/IFCGeometry.cpp index 83afd2b59..d488b2376 100644 --- a/code/AssetLib/IFC/IFCGeometry.cpp +++ b/code/AssetLib/IFC/IFCGeometry.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/IFC/IFCLoader.cpp b/code/AssetLib/IFC/IFCLoader.cpp index c919d9982..13ea2d429 100644 --- a/code/AssetLib/IFC/IFCLoader.cpp +++ b/code/AssetLib/IFC/IFCLoader.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -220,7 +220,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy std::unique_ptr db(STEP::ReadFileHeader(std::move(stream))); const STEP::HeaderInfo &head = static_cast(*db).GetHeader(); - if (!head.fileSchema.size() || head.fileSchema.substr(0, 3) != "IFC") { + if (!head.fileSchema.size() || head.fileSchema.substr(0, 4) != "IFC2") { ThrowException("Unrecognized file schema: " + head.fileSchema); } @@ -260,6 +260,8 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy ThrowException("missing IfcProject entity"); } + + ConversionData conv(*db, proj->To(), pScene, settings); SetUnits(conv); SetCoordinateSpace(conv); @@ -352,6 +354,11 @@ void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &co // ------------------------------------------------------------------------------------------------ void SetUnits(ConversionData &conv) { + if (conv.proj.UnitsInContext == nullptr) { + IFCImporter::LogError("Skipping conversion data, nullptr."); + return; + } + // see if we can determine the coordinate space used to express. for (size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i) { ConvertUnit(*conv.proj.UnitsInContext->Units[i], conv); diff --git a/code/AssetLib/IFC/IFCLoader.h b/code/AssetLib/IFC/IFCLoader.h index 9651b633a..d518650b7 100644 --- a/code/AssetLib/IFC/IFCLoader.h +++ b/code/AssetLib/IFC/IFCLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/IFC/IFCMaterial.cpp b/code/AssetLib/IFC/IFCMaterial.cpp index 0b7b83e7c..fd4003a67 100644 --- a/code/AssetLib/IFC/IFCMaterial.cpp +++ b/code/AssetLib/IFC/IFCMaterial.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/IFC/IFCOpenings.cpp b/code/AssetLib/IFC/IFCOpenings.cpp index c47446dda..1d37dd8ef 100644 --- a/code/AssetLib/IFC/IFCOpenings.cpp +++ b/code/AssetLib/IFC/IFCOpenings.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/IFC/IFCProfile.cpp b/code/AssetLib/IFC/IFCProfile.cpp index 0e4670560..72a96c29b 100644 --- a/code/AssetLib/IFC/IFCProfile.cpp +++ b/code/AssetLib/IFC/IFCProfile.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/IFC/IFCUtil.cpp b/code/AssetLib/IFC/IFCUtil.cpp index 27f3141c8..3977e22b5 100644 --- a/code/AssetLib/IFC/IFCUtil.cpp +++ b/code/AssetLib/IFC/IFCUtil.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/IFC/IFCUtil.h b/code/AssetLib/IFC/IFCUtil.h index f9063ce22..885bcb48f 100644 --- a/code/AssetLib/IFC/IFCUtil.h +++ b/code/AssetLib/IFC/IFCUtil.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Irr/IRRLoader.cpp b/code/AssetLib/Irr/IRRLoader.cpp index 2a481a6d8..12ce86260 100644 --- a/code/AssetLib/Irr/IRRLoader.cpp +++ b/code/AssetLib/Irr/IRRLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -168,7 +168,7 @@ void IRRImporter::BuildSkybox(std::vector &meshes, std::vectorAddProperty(&s, AI_MATKEY_NAME); int shading = aiShadingMode_NoShading; @@ -316,7 +316,7 @@ void IRRImporter::ComputeAnimations(Node *root, aiNode *real, std::vectormNodeName.length = ::ai_snprintf(anim->mNodeName.data, MAXLEN, + anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, AI_MAXLEN, "$INST_DUMMY_%i_%s", total - 1, (root->name.length() ? root->name.c_str() : "")); diff --git a/code/AssetLib/Irr/IRRLoader.h b/code/AssetLib/Irr/IRRLoader.h index 72ad5d35e..2a8bfd562 100644 --- a/code/AssetLib/Irr/IRRLoader.h +++ b/code/AssetLib/Irr/IRRLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Irr/IRRMeshLoader.cpp b/code/AssetLib/Irr/IRRMeshLoader.cpp index b35a95c12..4a2f70882 100644 --- a/code/AssetLib/Irr/IRRMeshLoader.cpp +++ b/code/AssetLib/Irr/IRRMeshLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -69,14 +69,6 @@ static constexpr aiImporterDesc desc = { "xml irrmesh" }; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -IRRMeshImporter::IRRMeshImporter() = default; - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -IRRMeshImporter::~IRRMeshImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool IRRMeshImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { @@ -116,8 +108,9 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, std::unique_ptr file(pIOHandler->Open(pFile)); // Check whether we can read from the file - if (file == nullptr) + if (file == nullptr) { throw DeadlyImportError("Failed to open IRRMESH file ", pFile); + } // Construct the irrXML parser XmlParser parser; @@ -148,13 +141,11 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, // int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents bool useColors = false; - /* - ** irrmesh files have a top level owning multiple nodes. - ** Each contains , , and - ** tags here directly owns the material data specs - ** are a vertex per line, contains position, UV1 coords, maybe UV2, normal, tangent, bitangent - ** is ignored, I think assimp recalculates those? - */ + // irrmesh files have a top level owning multiple nodes. + // Each contains , , and + // tags here directly owns the material data specs + // are a vertex per line, contains position, UV1 coords, maybe UV2, normal, tangent, bitangent + // is ignored, I think assimp recalculates those? // Parse the XML file pugi::xml_node const &meshNode = root.child("mesh"); @@ -201,7 +192,6 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, // This is possible ... remove the mesh from the list and skip further reading ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero vertices"); releaseMaterial(&curMat); - // releaseMesh(&curMesh); continue; // Bail out early }; @@ -250,7 +240,9 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, }; // We know what format buffer is, collect numbers - ParseBufferVertices(verticesNode.text().get(), vertexFormat, + std::string v = verticesNode.text().get(); + const char *end = v.c_str() + v.size(); + ParseBufferVertices(v.c_str(), end, vertexFormat, curVertices, curNormals, curTangents, curBitangents, curUVs, curUV2s, curColors, useColors); @@ -329,8 +321,10 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, // NOTE this might explode for UTF-16 and wchars const char *sz = indicesNode.text().get(); + const char *end = sz + std::strlen(sz); + // For each index loop over aiMesh faces - while (SkipSpacesAndLineEnd(&sz)) { + while (SkipSpacesAndLineEnd(&sz, end)) { if (curFace >= faceEnd) { ASSIMP_LOG_ERROR("IRRMESH: Too many indices"); break; @@ -354,12 +348,18 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, // Copy over data to aiMesh *pcV++ = curVertices[idx]; - if (pcN) *pcN++ = curNormals[idx]; - if (pcT) *pcT++ = curTangents[idx]; - if (pcB) *pcB++ = curBitangents[idx]; - if (pcC0) *pcC0++ = curColors[idx]; - if (pcT0) *pcT0++ = curUVs[idx]; - if (pcT1) *pcT1++ = curUV2s[idx]; + if (pcN) + *pcN++ = curNormals[idx]; + if (pcT) + *pcT++ = curTangents[idx]; + if (pcB) + *pcB++ = curBitangents[idx]; + if (pcC0) + *pcC0++ = curColors[idx]; + if (pcT0) + *pcT0++ = curUVs[idx]; + if (pcT1) + *pcT1++ = curUV2s[idx]; // start new face if (++curIdx == 3) { @@ -368,8 +368,9 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, } } // We should be at the end of mFaces - if (curFace != faceEnd) + if (curFace != faceEnd) { ASSIMP_LOG_ERROR("IRRMESH: Not enough indices"); + } } // Finish processing the mesh - do some small material workarounds @@ -379,8 +380,7 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, aiMaterial *mat = (aiMaterial *)curMat; mat->AddProperty(&curColors[0].a, 1, AI_MATKEY_OPACITY); } - // textMeaning = 2; - + // end of previous buffer. A material and a mesh should be there if (!curMat || !curMesh) { ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material"); @@ -421,37 +421,37 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, }; } -void IRRMeshImporter::ParseBufferVertices(const char *sz, VertexFormat vertexFormat, +void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, VertexFormat vertexFormat, std::vector &vertices, std::vector &normals, std::vector &tangents, std::vector &bitangents, std::vector &UVs, std::vector &UV2s, std::vector &colors, bool &useColors) { // read vertices do { - SkipSpacesAndLineEnd(&sz); + SkipSpacesAndLineEnd(&sz, end); aiVector3D temp; aiColor4D c; // Read the vertex position sz = fast_atoreal_move(sz, (float &)temp.x); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.y); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.z); - SkipSpaces(&sz); + SkipSpaces(&sz, end); vertices.push_back(temp); // Read the vertex normals sz = fast_atoreal_move(sz, (float &)temp.x); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.y); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.z); - SkipSpaces(&sz); + SkipSpaces(&sz, end); normals.push_back(temp); // read the vertex colors @@ -463,14 +463,14 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, VertexFormat vertexFor useColors = true; colors.push_back(c); - SkipSpaces(&sz); + SkipSpaces(&sz, end); // read the first UV coordinate set sz = fast_atoreal_move(sz, (float &)temp.x); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.y); - SkipSpaces(&sz); + SkipSpaces(&sz, end); temp.z = 0.f; temp.y = 1.f - temp.y; // DX to OGL UVs.push_back(temp); @@ -480,7 +480,7 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, VertexFormat vertexFor // read the (optional) second UV coordinate set if (vertexFormat == VertexFormat::t2coord) { sz = fast_atoreal_move(sz, (float &)temp.x); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.y); temp.y = 1.f - temp.y; // DX to OGL @@ -490,33 +490,32 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, VertexFormat vertexFor else if (vertexFormat == VertexFormat::tangent) { // tangents sz = fast_atoreal_move(sz, (float &)temp.x); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.z); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.y); - SkipSpaces(&sz); + SkipSpaces(&sz, end); temp.y *= -1.0f; tangents.push_back(temp); // bitangents sz = fast_atoreal_move(sz, (float &)temp.x); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.z); - SkipSpaces(&sz); + SkipSpaces(&sz, end); sz = fast_atoreal_move(sz, (float &)temp.y); - SkipSpaces(&sz); + SkipSpaces(&sz, end); temp.y *= -1.0f; bitangents.push_back(temp); } - } while (SkipLine(&sz)); - /* IMPORTANT: We assume that each vertex is specified in one - line. So we can skip the rest of the line - unknown vertex - elements are ignored. - */ + } while (SkipLine(&sz, end)); + // IMPORTANT: We assume that each vertex is specified in one + // line. So we can skip the rest of the line - unknown vertex + // elements are ignored. } #endif // !! ASSIMP_BUILD_NO_IRRMESH_IMPORTER diff --git a/code/AssetLib/Irr/IRRMeshLoader.h b/code/AssetLib/Irr/IRRMeshLoader.h index 620e40dba..4ab3615ee 100644 --- a/code/AssetLib/Irr/IRRMeshLoader.h +++ b/code/AssetLib/Irr/IRRMeshLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -62,8 +62,11 @@ namespace Assimp { */ class IRRMeshImporter : public BaseImporter, public IrrlichtBase { public: - IRRMeshImporter(); - ~IRRMeshImporter() override; + /// @brief The class constructor. + IRRMeshImporter() = default; + + /// @brief The class destructor. + ~IRRMeshImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. @@ -93,7 +96,7 @@ private: tangent = 2, // "tangents" - standard + tangents and bitangents }; - void ParseBufferVertices(const char *sz, VertexFormat vertexFormat, + void ParseBufferVertices(const char *sz, const char *end, VertexFormat vertexFormat, std::vector &vertices, std::vector &normals, std::vector &tangents, std::vector &bitangents, std::vector &UVs, std::vector &UV2s, diff --git a/code/AssetLib/Irr/IRRShared.cpp b/code/AssetLib/Irr/IRRShared.cpp index a47aeccba..20d56bb02 100644 --- a/code/AssetLib/Irr/IRRShared.cpp +++ b/code/AssetLib/Irr/IRRShared.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -135,21 +135,23 @@ void IrrlichtBase::ReadVectorProperty(VectorProperty &out, pugi::xml_node& vecto } else if (!ASSIMP_stricmp(attrib.name(), "value")) { // three floats, separated with commas const char *ptr = attrib.value(); + size_t len = std::strlen(ptr); + const char *end = ptr + len; - SkipSpaces(&ptr); + SkipSpaces(&ptr, end); ptr = fast_atoreal_move(ptr, (float &)out.value.x); - SkipSpaces(&ptr); + SkipSpaces(&ptr, end); if (',' != *ptr) { ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition"); } else { - SkipSpaces(ptr + 1, &ptr); + SkipSpaces(ptr + 1, &ptr, end); } ptr = fast_atoreal_move(ptr, (float &)out.value.y); - SkipSpaces(&ptr); + SkipSpaces(&ptr, end); if (',' != *ptr) { ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition"); } else { - SkipSpaces(ptr + 1, &ptr); + SkipSpaces(ptr + 1, &ptr, end); } ptr = fast_atoreal_move(ptr, (float &)out.value.z); } diff --git a/code/AssetLib/LWO/LWOAnimation.cpp b/code/AssetLib/LWO/LWOAnimation.cpp index 8dda4586f..5b9c6882e 100644 --- a/code/AssetLib/LWO/LWOAnimation.cpp +++ b/code/AssetLib/LWO/LWOAnimation.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/LWO/LWOAnimation.h b/code/AssetLib/LWO/LWOAnimation.h index 1e419d461..9daa7009c 100644 --- a/code/AssetLib/LWO/LWOAnimation.h +++ b/code/AssetLib/LWO/LWOAnimation.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/LWO/LWOBLoader.cpp b/code/AssetLib/LWO/LWOBLoader.cpp index 4a9792b79..b5c14f158 100644 --- a/code/AssetLib/LWO/LWOBLoader.cpp +++ b/code/AssetLib/LWO/LWOBLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team @@ -152,7 +152,7 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face } // ------------------------------------------------------------------------------------------------ -void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, +void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator &it, LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max) { diff --git a/code/AssetLib/LWO/LWOFileData.h b/code/AssetLib/LWO/LWOFileData.h index 656dd4529..c81111251 100644 --- a/code/AssetLib/LWO/LWOFileData.h +++ b/code/AssetLib/LWO/LWOFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/LWO/LWOLoader.cpp b/code/AssetLib/LWO/LWOLoader.cpp index 7e93b65f8..025ca7408 100644 --- a/code/AssetLib/LWO/LWOLoader.cpp +++ b/code/AssetLib/LWO/LWOLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/LWO/LWOLoader.h b/code/AssetLib/LWO/LWOLoader.h index 9e116a3cc..3f81ff449 100644 --- a/code/AssetLib/LWO/LWOLoader.h +++ b/code/AssetLib/LWO/LWOLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/LWO/LWOMaterial.cpp b/code/AssetLib/LWO/LWOMaterial.cpp index 8d83dfb67..1d7d137e1 100644 --- a/code/AssetLib/LWO/LWOMaterial.cpp +++ b/code/AssetLib/LWO/LWOMaterial.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/AssetLib/LWS/LWSLoader.cpp b/code/AssetLib/LWS/LWSLoader.cpp index dec834495..047ab0cc9 100644 --- a/code/AssetLib/LWS/LWSLoader.cpp +++ b/code/AssetLib/LWS/LWSLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -78,14 +78,14 @@ static constexpr aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Recursive parsing of LWS files -void LWS::Element::Parse(const char *&buffer) { - for (; SkipSpacesAndLineEnd(&buffer); SkipLine(&buffer)) { +void LWS::Element::Parse(const char *&buffer, const char *end) { + for (; SkipSpacesAndLineEnd(&buffer, end); SkipLine(&buffer, end)) { // begin of a new element with children bool sub = false; if (*buffer == '{') { ++buffer; - SkipSpaces(&buffer); + SkipSpaces(&buffer, end); sub = true; } else if (*buffer == '}') return; @@ -98,16 +98,15 @@ void LWS::Element::Parse(const char *&buffer) { while (!IsSpaceOrNewLine(*buffer)) ++buffer; children.back().tokens[0] = std::string(cur, (size_t)(buffer - cur)); - SkipSpaces(&buffer); + SkipSpaces(&buffer, end); if (children.back().tokens[0] == "Plugin") { ASSIMP_LOG_VERBOSE_DEBUG("LWS: Skipping over plugin-specific data"); // strange stuff inside Plugin/Endplugin blocks. Needn't // follow LWS syntax, so we skip over it - for (; SkipSpacesAndLineEnd(&buffer); SkipLine(&buffer)) { + for (; SkipSpacesAndLineEnd(&buffer, end); SkipLine(&buffer, end)) { if (!::strncmp(buffer, "EndPlugin", 9)) { - //SkipLine(&buffer); break; } } @@ -122,7 +121,7 @@ void LWS::Element::Parse(const char *&buffer) { // parse more elements recursively if (sub) { - children.back().Parse(buffer); + children.back().Parse(buffer, end); } } } @@ -155,6 +154,8 @@ const aiImporterDesc *LWSImporter::GetInfo() const { return &desc; } +static constexpr int MagicHackNo = 150392; + // ------------------------------------------------------------------------------------------------ // Setup configuration properties void LWSImporter::SetupProperties(const Importer *pImp) { @@ -163,11 +164,11 @@ void LWSImporter::SetupProperties(const Importer *pImp) { // AI_CONFIG_IMPORT_LWS_ANIM_START first = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_START, - 150392 /* magic hack */); + MagicHackNo /* magic hack */); // AI_CONFIG_IMPORT_LWS_ANIM_END last = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_END, - 150392 /* magic hack */); + MagicHackNo /* magic hack */); if (last < first) { std::swap(last, first); @@ -191,15 +192,16 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) { for (++it; it != dad.children.end(); ++it) { const char *c = (*it).tokens[1].c_str(); + const char *end = c + (*it).tokens[1].size(); if ((*it).tokens[0] == "Key") { fill.keys.emplace_back(); LWO::Key &key = fill.keys.back(); float f; - SkipSpaces(&c); + SkipSpaces(&c, end); c = fast_atoreal_move(c, key.value); - SkipSpaces(&c); + SkipSpaces(&c, end); c = fast_atoreal_move(c, f); key.time = f; @@ -231,13 +233,13 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) { ASSIMP_LOG_ERROR("LWS: Unknown span type"); } for (unsigned int i = 0; i < num; ++i) { - SkipSpaces(&c); + SkipSpaces(&c, end); c = fast_atoreal_move(c, key.params[i]); } } else if ((*it).tokens[0] == "Behaviors") { - SkipSpaces(&c); + SkipSpaces(&c, end); fill.pre = (LWO::PrePostBehaviour)strtoul10(c, &c); - SkipSpaces(&c); + SkipSpaces(&c, end); fill.post = (LWO::PrePostBehaviour)strtoul10(c, &c); } } @@ -245,47 +247,45 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) { // ------------------------------------------------------------------------------------------------ // Read animation channels in the old LightWave animation format -void LWSImporter::ReadEnvelope_Old( - std::list::const_iterator &it, - const std::list::const_iterator &end, - LWS::NodeDesc &nodes, - unsigned int /*version*/) { - unsigned int num, sub_num; - if (++it == end) goto unexpected_end; +void LWSImporter::ReadEnvelope_Old(std::list::const_iterator &it,const std::list::const_iterator &endIt, + LWS::NodeDesc &nodes, unsigned int) { + if (++it == endIt) { + ASSIMP_LOG_ERROR("LWS: Encountered unexpected end of file while parsing object motion"); + return; + } - num = strtoul10((*it).tokens[0].c_str()); + const unsigned int num = strtoul10((*it).tokens[0].c_str()); for (unsigned int i = 0; i < num; ++i) { - nodes.channels.emplace_back(); LWO::Envelope &envl = nodes.channels.back(); envl.index = i; envl.type = (LWO::EnvelopeType)(i + 1); - if (++it == end) { - goto unexpected_end; + if (++it == endIt) { + ASSIMP_LOG_ERROR("LWS: Encountered unexpected end of file while parsing object motion"); + return; } - sub_num = strtoul10((*it).tokens[0].c_str()); - + + const unsigned int sub_num = strtoul10((*it).tokens[0].c_str()); for (unsigned int n = 0; n < sub_num; ++n) { - - if (++it == end) goto unexpected_end; + if (++it == endIt) { + ASSIMP_LOG_ERROR("LWS: Encountered unexpected end of file while parsing object motion"); + return; + } // parse value and time, skip the rest for the moment. LWO::Key key; const char *c = fast_atoreal_move((*it).tokens[0].c_str(), key.value); - SkipSpaces(&c); + const char *end = c + (*it).tokens[0].size(); + SkipSpaces(&c, end); float f; fast_atoreal_move((*it).tokens[0].c_str(), f); key.time = f; - envl.keys.push_back(key); + envl.keys.emplace_back(key); } } - return; - -unexpected_end: - ASSIMP_LOG_ERROR("LWS: Encountered unexpected end of file while parsing object motion"); } // ------------------------------------------------------------------------------------------------ @@ -296,7 +296,6 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) { // the name depends on the type. We break LWS's strange naming convention // and return human-readable, but still machine-parsable and unique, strings. if (src.type == LWS::NodeDesc::OBJECT) { - if (src.path.length()) { std::string::size_type s = src.path.find_last_of("\\/"); if (s == std::string::npos) { @@ -306,14 +305,14 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) { } std::string::size_type t = src.path.substr(s).find_last_of('.'); - nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined); - if (nd->mName.length > MAXLEN) { - nd->mName.length = MAXLEN; + nd->mName.length = ::ai_snprintf(nd->mName.data, AI_MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined); + if (nd->mName.length > AI_MAXLEN) { + nd->mName.length = AI_MAXLEN; } return; } } - nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.name, combined); + nd->mName.length = ::ai_snprintf(nd->mName.data, AI_MAXLEN, "%s_(%08X)", src.name, combined); } // ------------------------------------------------------------------------------------------------ @@ -501,7 +500,8 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // Parse the file structure LWS::Element root; const char *dummy = &mBuffer[0]; - root.Parse(dummy); + const char *dummyEnd = dummy + mBuffer.size(); + root.Parse(dummy, dummyEnd); // Construct a Batch-importer to read more files recursively BatchLoader batch(pIOHandler); @@ -540,6 +540,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // Now read all elements in a very straightforward manner for (; it != root.children.end(); ++it) { const char *c = (*it).tokens[1].c_str(); + const char *end = c + (*it).tokens[1].size(); // 'FirstFrame': begin of animation slice if ((*it).tokens[0] == "FirstFrame") { @@ -567,14 +568,14 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy LWS::NodeDesc d; d.type = LWS::NodeDesc::OBJECT; if (version >= 4) { // handle LWSC 4 explicit ID - SkipSpaces(&c); + SkipSpaces(&c, end); d.number = strtoul16(c, &c) & AI_LWS_MASK; } else { d.number = cur_object++; } // and add the file to the import list - SkipSpaces(&c); + SkipSpaces(&c, end); std::string path = FindLWOFile(c); d.path = path; d.id = batch.AddLoadRequest(path, 0, &props); @@ -588,7 +589,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy if (version >= 4) { // handle LWSC 4 explicit ID d.number = strtoul16(c, &c) & AI_LWS_MASK; - SkipSpaces(&c); + SkipSpaces(&c, end); } else { d.number = cur_object++; } @@ -604,7 +605,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy d.type = LWS::NodeDesc::OBJECT; if (version >= 4) { // handle LWSC 4 explicit ID d.number = strtoul16(c, &c) & AI_LWS_MASK; - SkipSpaces(&c); + SkipSpaces(&c, end); } else { d.number = cur_object++; } @@ -668,26 +669,25 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // two ints per envelope LWO::Envelope &env = *envelopeIt; env.pre = (LWO::PrePostBehaviour)strtoul10(c, &c); - SkipSpaces(&c); + SkipSpaces(&c, end); env.post = (LWO::PrePostBehaviour)strtoul10(c, &c); - SkipSpaces(&c); + SkipSpaces(&c, end); } } } // 'ParentItem': specifies the parent of the current element else if ((*it).tokens[0] == "ParentItem") { - if (nodes.empty()) + if (nodes.empty()) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentItem\'"); - - else + } else { nodes.back().parent = strtoul16(c, &c); + } } // 'ParentObject': deprecated one for older formats else if (version < 3 && (*it).tokens[0] == "ParentObject") { - if (nodes.empty()) + if (nodes.empty()) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentObject\'"); - - else { + } else { nodes.back().parent = strtoul10(c, &c) | (1u << 28u); } } @@ -700,19 +700,20 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy if (version >= 4) { // handle LWSC 4 explicit ID d.number = strtoul16(c, &c) & AI_LWS_MASK; - } else + } else { d.number = cur_camera++; + } nodes.push_back(d); num_camera++; } // 'CameraName': set name of currently active camera else if ((*it).tokens[0] == "CameraName") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA) + if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'CameraName\'"); - - else + } else { nodes.back().name = c; + } } // 'AddLight': add a light to the scenegraph else if ((*it).tokens[0] == "AddLight") { @@ -723,19 +724,20 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy if (version >= 4) { // handle LWSC 4 explicit ID d.number = strtoul16(c, &c) & AI_LWS_MASK; - } else + } else { d.number = cur_light++; + } nodes.push_back(d); num_light++; } // 'LightName': set name of currently active light else if ((*it).tokens[0] == "LightName") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) + if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightName\'"); - - else + } else { nodes.back().name = c; + } } // 'LightIntensity': set intensity of currently active light else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity") { @@ -753,62 +755,58 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy } // 'LightType': set type of currently active light else if ((*it).tokens[0] == "LightType") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) + if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightType\'"); - - else + } else { nodes.back().lightType = strtoul10(c); - + } } // 'LightFalloffType': set falloff type of currently active light else if ((*it).tokens[0] == "LightFalloffType") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) + if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightFalloffType\'"); - else + } else { nodes.back().lightFalloffType = strtoul10(c); - + } } // 'LightConeAngle': set cone angle of currently active light else if ((*it).tokens[0] == "LightConeAngle") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) + if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightConeAngle\'"); - - else + } else { nodes.back().lightConeAngle = fast_atof(c); - + } } // 'LightEdgeAngle': set area where we're smoothing from min to max intensity else if ((*it).tokens[0] == "LightEdgeAngle") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) + if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightEdgeAngle\'"); - - else + } else { nodes.back().lightEdgeAngle = fast_atof(c); - + } } // 'LightColor': set color of currently active light else if ((*it).tokens[0] == "LightColor") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) + if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'"); - - else { + } else { c = fast_atoreal_move(c, (float &)nodes.back().lightColor.r); - SkipSpaces(&c); + SkipSpaces(&c, end); c = fast_atoreal_move(c, (float &)nodes.back().lightColor.g); - SkipSpaces(&c); + SkipSpaces(&c, end); c = fast_atoreal_move(c, (float &)nodes.back().lightColor.b); } } // 'PivotPosition': position of local transformation origin else if ((*it).tokens[0] == "PivotPosition" || (*it).tokens[0] == "PivotPoint") { - if (nodes.empty()) + if (nodes.empty()) { ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'"); - else { + } else { c = fast_atoreal_move(c, (float &)nodes.back().pivotPos.x); - SkipSpaces(&c); + SkipSpaces(&c, end); c = fast_atoreal_move(c, (float &)nodes.back().pivotPos.y); - SkipSpaces(&c); + SkipSpaces(&c, end); c = fast_atoreal_move(c, (float &)nodes.back().pivotPos.z); // Mark pivotPos as set nodes.back().isPivotSet = true; @@ -818,7 +816,6 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // resolve parenting for (std::list::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) { - // check whether there is another node which calls us a parent for (std::list::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) { if (dit != ndIt && *ndIt == (*dit).parent) { @@ -854,7 +851,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy aiNode *nd = master->mRootNode = new aiNode(); // allocate storage for cameras&lights - if (num_camera) { + if (num_camera > 0u) { master->mCameras = new aiCamera *[master->mNumCameras = num_camera]; } aiCamera **cams = master->mCameras; diff --git a/code/AssetLib/LWS/LWSLoader.h b/code/AssetLib/LWS/LWSLoader.h index 4e92ef0d5..f66688249 100644 --- a/code/AssetLib/LWS/LWSLoader.h +++ b/code/AssetLib/LWS/LWSLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -76,7 +76,7 @@ public: std::list children; //! Recursive parsing function - void Parse(const char *&buffer); + void Parse(const char *&buffer, const char *end); }; #define AI_LWS_MASK (0xffffffff >> 4u) diff --git a/code/AssetLib/M3D/M3DExporter.cpp b/code/AssetLib/M3D/M3DExporter.cpp index cf87b6221..5545be415 100644 --- a/code/AssetLib/M3D/M3DExporter.cpp +++ b/code/AssetLib/M3D/M3DExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team Copyright (c) 2019 bzt All rights reserved. diff --git a/code/AssetLib/M3D/M3DExporter.h b/code/AssetLib/M3D/M3DExporter.h index d77743f56..0e9ab4305 100644 --- a/code/AssetLib/M3D/M3DExporter.h +++ b/code/AssetLib/M3D/M3DExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team Copyright (c) 2019 bzt All rights reserved. diff --git a/code/AssetLib/M3D/M3DImporter.cpp b/code/AssetLib/M3D/M3DImporter.cpp index 71f416139..b74b72dc8 100644 --- a/code/AssetLib/M3D/M3DImporter.cpp +++ b/code/AssetLib/M3D/M3DImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team Copyright (c) 2019 bzt All rights reserved. diff --git a/code/AssetLib/M3D/M3DImporter.h b/code/AssetLib/M3D/M3DImporter.h index 9ca8f9211..d9e546f39 100644 --- a/code/AssetLib/M3D/M3DImporter.h +++ b/code/AssetLib/M3D/M3DImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team Copyright (c) 2019 bzt All rights reserved. diff --git a/code/AssetLib/M3D/M3DMaterials.h b/code/AssetLib/M3D/M3DMaterials.h index a1b0fd742..dc87a99c7 100644 --- a/code/AssetLib/M3D/M3DMaterials.h +++ b/code/AssetLib/M3D/M3DMaterials.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team Copyright (c) 2019 bzt All rights reserved. diff --git a/code/AssetLib/M3D/M3DWrapper.cpp b/code/AssetLib/M3D/M3DWrapper.cpp index 05087d592..3741bbca3 100644 --- a/code/AssetLib/M3D/M3DWrapper.cpp +++ b/code/AssetLib/M3D/M3DWrapper.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team Copyright (c) 2019 bzt All rights reserved. diff --git a/code/AssetLib/M3D/M3DWrapper.h b/code/AssetLib/M3D/M3DWrapper.h index 880aca996..8a3fd92be 100644 --- a/code/AssetLib/M3D/M3DWrapper.h +++ b/code/AssetLib/M3D/M3DWrapper.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team Copyright (c) 2019 bzt All rights reserved. diff --git a/code/AssetLib/MD2/MD2FileData.h b/code/AssetLib/MD2/MD2FileData.h index 3bce8feee..0dba71e56 100644 --- a/code/AssetLib/MD2/MD2FileData.h +++ b/code/AssetLib/MD2/MD2FileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace MD2 { -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" #define AI_MD2_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP2") #define AI_MD2_MAGIC_NUMBER_LE AI_MAKE_MAGIC("2PDI") diff --git a/code/AssetLib/MD2/MD2Loader.cpp b/code/AssetLib/MD2/MD2Loader.cpp index 596d26414..99dc70d08 100644 --- a/code/AssetLib/MD2/MD2Loader.cpp +++ b/code/AssetLib/MD2/MD2Loader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MD2/MD2Loader.h b/code/AssetLib/MD2/MD2Loader.h index bab026ea0..5ac34ad4c 100644 --- a/code/AssetLib/MD2/MD2Loader.h +++ b/code/AssetLib/MD2/MD2Loader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MD2/MD2NormalTable.h b/code/AssetLib/MD2/MD2NormalTable.h index 1837939e8..7d13b9ad1 100644 --- a/code/AssetLib/MD2/MD2NormalTable.h +++ b/code/AssetLib/MD2/MD2NormalTable.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MD3/MD3FileData.h b/code/AssetLib/MD3/MD3FileData.h index 01475e679..86d2647b6 100644 --- a/code/AssetLib/MD3/MD3FileData.h +++ b/code/AssetLib/MD3/MD3FileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -62,7 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace MD3 { -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" #define AI_MD3_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP3") #define AI_MD3_MAGIC_NUMBER_LE AI_MAKE_MAGIC("3PDI") diff --git a/code/AssetLib/MD3/MD3Loader.cpp b/code/AssetLib/MD3/MD3Loader.cpp index e743889e3..3dd8d9c66 100644 --- a/code/AssetLib/MD3/MD3Loader.cpp +++ b/code/AssetLib/MD3/MD3Loader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team @@ -123,12 +123,12 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem * // remove comments from it (C++ style) CommentRemover::RemoveLineComments("//", &_buff[0]); const char *buff = &_buff[0]; - + const char *end = buff + _buff.size(); Q3Shader::ShaderDataBlock *curData = nullptr; Q3Shader::ShaderMapBlock *curMap = nullptr; // read line per line - for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) { + for (; SkipSpacesAndLineEnd(&buff, end); SkipLine(&buff, end)) { if (*buff == '{') { ++buff; @@ -140,21 +140,21 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem * } // read this data section - for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) { + for (; SkipSpacesAndLineEnd(&buff, end); SkipLine(&buff, end)) { if (*buff == '{') { ++buff; // add new map section curData->maps.emplace_back(); curMap = &curData->maps.back(); - for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) { + for (; SkipSpacesAndLineEnd(&buff, end); SkipLine(&buff, end)) { // 'map' - Specifies texture file name if (TokenMatchI(buff, "map", 3) || TokenMatchI(buff, "clampmap", 8)) { - curMap->name = GetNextToken(buff); + curMap->name = GetNextToken(buff, end); } // 'blendfunc' - Alpha blending mode else if (TokenMatchI(buff, "blendfunc", 9)) { - const std::string blend_src = GetNextToken(buff); + const std::string blend_src = GetNextToken(buff, end); if (blend_src == "add") { curMap->blend_src = Q3Shader::BLEND_GL_ONE; curMap->blend_dest = Q3Shader::BLEND_GL_ONE; @@ -166,12 +166,12 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem * curMap->blend_dest = Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA; } else { curMap->blend_src = StringToBlendFunc(blend_src); - curMap->blend_dest = StringToBlendFunc(GetNextToken(buff)); + curMap->blend_dest = StringToBlendFunc(GetNextToken(buff, end)); } } // 'alphafunc' - Alpha testing mode else if (TokenMatchI(buff, "alphafunc", 9)) { - const std::string at = GetNextToken(buff); + const std::string at = GetNextToken(buff, end); if (at == "GT0") { curMap->alpha_test = Q3Shader::AT_GT0; } else if (at == "LT128") { @@ -186,7 +186,6 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem * break; } } - } else if (*buff == '}') { ++buff; curData = nullptr; @@ -195,7 +194,7 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem * // 'cull' specifies culling behaviour for the model else if (TokenMatchI(buff, "cull", 4)) { - SkipSpaces(&buff); + SkipSpaces(&buff, end); if (!ASSIMP_strincmp(buff, "back", 4)) { // render face's backside, does not function in Q3 engine (bug) curData->cull = Q3Shader::CULL_CCW; } else if (!ASSIMP_strincmp(buff, "front", 5)) { // is not valid keyword in Q3, but occurs in shaders @@ -213,9 +212,10 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem * curData = &fill.blocks.back(); // get the name of this section - curData->name = GetNextToken(buff); + curData->name = GetNextToken(buff, end); } } + return true; } @@ -232,6 +232,7 @@ bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io) const size_t s = file->FileSize(); std::vector _buff(s + 1); const char *buff = &_buff[0]; + const char *end = buff + _buff.size(); file->Read(&_buff[0], s, 1); _buff[s] = 0; @@ -240,10 +241,10 @@ bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io) // read token by token and fill output table for (; *buff;) { - SkipSpacesAndLineEnd(&buff); + SkipSpacesAndLineEnd(&buff, end); // get first identifier - std::string ss = GetNextToken(buff); + std::string ss = GetNextToken(buff, end); // ignore tokens starting with tag_ if (!::strncmp(&ss[0], "tag_", std::min((size_t)4, ss.length()))) @@ -253,8 +254,9 @@ bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io) SkinData::TextureEntry &entry = fill.textures.back(); entry.first = ss; - entry.second = GetNextToken(buff); + entry.second = GetNextToken(buff, end); } + return true; } @@ -293,7 +295,7 @@ void Q3Shader::ConvertShaderToMaterial(aiMaterial *out, const ShaderDataBlock &s // - in any case: set it as diffuse texture // // If the texture is using 'filter' blending - // - take as lightmap + // - take as light-map // // Textures with alpha funcs // - aiTextureFlags_UseAlpha is set (otherwise aiTextureFlags_NoAlpha is explicitly set) diff --git a/code/AssetLib/MD3/MD3Loader.h b/code/AssetLib/MD3/MD3Loader.h index d911bb1da..eee66a3df 100644 --- a/code/AssetLib/MD3/MD3Loader.h +++ b/code/AssetLib/MD3/MD3Loader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MD5/MD5Loader.cpp b/code/AssetLib/MD5/MD5Loader.cpp index 697e758fb..02f08d3ea 100644 --- a/code/AssetLib/MD5/MD5Loader.cpp +++ b/code/AssetLib/MD5/MD5Loader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -210,7 +210,7 @@ void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) { const unsigned int guess = (unsigned int)(fWeightsPerVert * iNewNum); meshSrc.mWeights.reserve(guess + (guess >> 3)); // + 12.5% as buffer - for (FaceList::const_iterator iter = meshSrc.mFaces.begin(), iterEnd = meshSrc.mFaces.end(); iter != iterEnd; ++iter) { + for (FaceArray::const_iterator iter = meshSrc.mFaces.begin(), iterEnd = meshSrc.mFaces.end(); iter != iterEnd; ++iter) { const aiFace &face = *iter; for (unsigned int i = 0; i < 3; ++i) { if (face.mIndices[0] >= meshSrc.mVertices.size()) { @@ -231,7 +231,7 @@ void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) { // ------------------------------------------------------------------------------------------------ // Recursive node graph construction from a MD5MESH -void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) { +void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneArray &bones) { ai_assert(nullptr != piParent); ai_assert(!piParent->mNumChildren); @@ -282,7 +282,7 @@ void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &b // ------------------------------------------------------------------------------------------------ // Recursive node graph construction from a MD5ANIM -void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) { +void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneArray &bones, const aiNodeAnim **node_anims) { ai_assert(nullptr != piParent); ai_assert(!piParent->mNumChildren); @@ -402,7 +402,7 @@ void MD5Importer::LoadMD5MeshFile() { // copy texture coordinates aiVector3D *pv = mesh->mTextureCoords[0]; - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { + for (MD5::VertexArray::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { pv->x = (*iter).mUV.x; pv->y = 1.0f - (*iter).mUV.y; // D3D to OpenGL pv->z = 0.0f; @@ -412,7 +412,7 @@ void MD5Importer::LoadMD5MeshFile() { unsigned int *piCount = new unsigned int[meshParser.mJoints.size()]; ::memset(piCount, 0, sizeof(unsigned int) * meshParser.mJoints.size()); - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { + for (MD5::VertexArray::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; /* FIX for some invalid exporters */ @@ -447,7 +447,7 @@ void MD5Importer::LoadMD5MeshFile() { } pv = mesh->mVertices; - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { + for (MD5::VertexArray::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { // compute the final vertex position from all single weights *pv = aiVector3D(); @@ -585,14 +585,14 @@ void MD5Importer::LoadMD5AnimFile() { // 1 tick == 1 frame anim->mTicksPerSecond = animParser.fFrameRate; - for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end(); iter != iterEnd; ++iter) { + for (FrameArray::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end(); iter != iterEnd; ++iter) { double dTime = (double)(*iter).iIndex; aiNodeAnim **pcAnimNode = anim->mChannels; if (!(*iter).mValues.empty() || iter == animParser.mFrames.begin()) /* be sure we have at least one frame */ { // now process all values in there ... read all joints MD5::BaseFrameDesc *pcBaseFrame = &animParser.mBaseFrames[0]; - for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end(); ++iter2, + for (AnimBoneArray::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end(); ++iter2, ++pcAnimNode, ++pcBaseFrame) { if ((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) { @@ -707,7 +707,7 @@ void MD5Importer::LoadMD5CameraFile() { for (std::vector::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) { aiAnimation *anim = *tmp++ = new aiAnimation(); - anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u", (unsigned int)(it - cuts.begin()), (*it), *(it + 1)); + anim->mName.length = ::ai_snprintf(anim->mName.data, AI_MAXLEN, "anim%u_from_%u_to_%u", (unsigned int)(it - cuts.begin()), (*it), *(it + 1)); anim->mTicksPerSecond = cameraParser.fFrameRate; anim->mChannels = new aiNodeAnim *[anim->mNumChannels = 1]; diff --git a/code/AssetLib/MD5/MD5Loader.h b/code/AssetLib/MD5/MD5Loader.h index c213c04e6..d64d6f5b8 100644 --- a/code/AssetLib/MD5/MD5Loader.h +++ b/code/AssetLib/MD5/MD5Loader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -118,7 +118,7 @@ protected: * @param node_anims Generated node animations */ void AttachChilds_Anim(int iParentID, aiNode *piParent, - AnimBoneList &bones, const aiNodeAnim **node_anims); + AnimBoneArray &bones, const aiNodeAnim **node_anims); // ------------------------------------------------------------------- /** Construct node hierarchy from a given MD5MESH @@ -126,7 +126,7 @@ protected: * @param piParent Parent node to attach to * @param bones Input bones */ - void AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones); + void AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneArray &bones); // ------------------------------------------------------------------- /** Build unique vertex buffers from a given MD5ANIM diff --git a/code/AssetLib/MD5/MD5Parser.cpp b/code/AssetLib/MD5/MD5Parser.cpp index 8da30e28f..24882af7e 100644 --- a/code/AssetLib/MD5/MD5Parser.cpp +++ b/code/AssetLib/MD5/MD5Parser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -138,14 +138,16 @@ bool MD5Parser::ParseSection(Section &out) { char *sz = buffer; while (!IsSpaceOrNewLine(*buffer)) { ++buffer; - if (buffer == bufferEnd) + if (buffer == bufferEnd) { return false; + } } out.mName = std::string(sz, (uintptr_t)(buffer - sz)); while (IsSpace(*buffer)) { ++buffer; - if (buffer == bufferEnd) + if (buffer == bufferEnd) { return false; + } } bool running = true; @@ -153,14 +155,16 @@ bool MD5Parser::ParseSection(Section &out) { if ('{' == *buffer) { // it is a normal section so read all lines ++buffer; - if (buffer == bufferEnd) + if (buffer == bufferEnd) { return false; + } bool run = true; while (run) { while (IsSpaceOrNewLine(*buffer)) { ++buffer; - if (buffer == bufferEnd) + if (buffer == bufferEnd) { return false; + } } if ('\0' == *buffer) { return false; // seems this was the last section @@ -175,18 +179,21 @@ bool MD5Parser::ParseSection(Section &out) { elem.iLineNumber = lineNumber; elem.szStart = buffer; + elem.end = bufferEnd; // terminate the line with zero while (!IsLineEnd(*buffer)) { ++buffer; - if (buffer == bufferEnd) + if (buffer == bufferEnd) { return false; + } } if (*buffer) { ++lineNumber; *buffer++ = '\0'; - if (buffer == bufferEnd) + if (buffer == bufferEnd) { return false; + } } } break; @@ -194,89 +201,107 @@ bool MD5Parser::ParseSection(Section &out) { // it is an element at global scope. Parse its value and go on sz = buffer; while (!IsSpaceOrNewLine(*buffer++)) { - if (buffer == bufferEnd) + if (buffer == bufferEnd) { return false; + } } out.mGlobalValue = std::string(sz, (uintptr_t)(buffer - sz)); continue; } break; } - if (buffer == bufferEnd) + if (buffer == bufferEnd) { return false; + } while (IsSpaceOrNewLine(*buffer)) { + if (buffer == bufferEnd) { + break; + } ++buffer; - if (buffer == bufferEnd) - return false; } return '\0' != *buffer; } -// ------------------------------------------------------------------------------------------------ -// Some dirty macros just because they're so funny and easy to debug - // skip all spaces ... handle EOL correctly -#define AI_MD5_SKIP_SPACES() \ - if (!SkipSpaces(&sz)) \ - MD5Parser::ReportWarning("Unexpected end of line", elem.iLineNumber); +inline void AI_MD5_SKIP_SPACES(const char **sz, const char *bufferEnd, int linenumber) { + if (!SkipSpaces(sz, bufferEnd)) { + MD5Parser::ReportWarning("Unexpected end of line", linenumber); + } +} // read a triple float in brackets: (1.0 1.0 1.0) -#define AI_MD5_READ_TRIPLE(vec) \ - AI_MD5_SKIP_SPACES(); \ - if ('(' != *sz++) \ - MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move(sz, (float &)vec.x); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move(sz, (float &)vec.y); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atoreal_move(sz, (float &)vec.z); \ - AI_MD5_SKIP_SPACES(); \ - if (')' != *sz++) \ - MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber); +inline void AI_MD5_READ_TRIPLE(aiVector3D &vec, const char **sz, const char *bufferEnd, int linenumber) { + AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); + if ('(' != **sz) { + MD5Parser::ReportWarning("Unexpected token: ( was expected", linenumber); + ++*sz; + } + ++*sz; + AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); + *sz = fast_atoreal_move(*sz, (float &)vec.x); + AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); + *sz = fast_atoreal_move(*sz, (float &)vec.y); + AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); + *sz = fast_atoreal_move(*sz, (float &)vec.z); + AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); + if (')' != **sz) { + MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber); + } + ++*sz; +} // parse a string, enclosed in quotation marks or not -#define AI_MD5_PARSE_STRING(out) \ - bool bQuota = (*sz == '\"'); \ - const char *szStart = sz; \ - while (!IsSpaceOrNewLine(*sz)) \ - ++sz; \ - const char *szEnd = sz; \ - if (bQuota) { \ - szStart++; \ - if ('\"' != *(szEnd -= 1)) { \ - MD5Parser::ReportWarning("Expected closing quotation marks in string", \ - elem.iLineNumber); \ - continue; \ - } \ - } \ - out.length = (size_t)(szEnd - szStart); \ - ::memcpy(out.data, szStart, out.length); \ +inline bool AI_MD5_PARSE_STRING(const char **sz, const char *bufferEnd, aiString &out, int linenumber) { + bool bQuota = (**sz == '\"'); + const char *szStart = *sz; + while (!IsSpaceOrNewLine(**sz)) { + ++*sz; + if (*sz == bufferEnd) break; + } + const char *szEnd = *sz; + if (bQuota) { + szStart++; + if ('\"' != *(szEnd -= 1)) { + MD5Parser::ReportWarning("Expected closing quotation marks in string", linenumber); + ++*sz; + } + } + out.length = (ai_uint32)(szEnd - szStart); + ::memcpy(out.data, szStart, out.length); out.data[out.length] = '\0'; + return true; +} + // parse a string, enclosed in quotation marks -#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \ - out.length = 0; \ - while ('\"' != *sz && '\0' != *sz) \ - ++sz; \ - if ('\0' != *sz) { \ - const char *szStart = ++sz; \ - while ('\"' != *sz && '\0' != *sz) \ - ++sz; \ - if ('\0' != *sz) { \ - const char *szEnd = (sz++); \ - out.length = (ai_uint32)(szEnd - szStart); \ - ::memcpy(out.data, szStart, out.length); \ - } \ - } \ +inline void AI_MD5_PARSE_STRING_IN_QUOTATION(const char **sz, const char *bufferEnd, aiString &out) { + out.length = 0u; + while (('\"' != **sz && '\0' != **sz) && *sz != bufferEnd) { + ++*sz; + } + if ('\0' != **sz) { + const char *szStart = ++(*sz); + + while (('\"' != **sz && '\0' != **sz) && *sz != bufferEnd) { + ++*sz; + } + if ('\0' != **sz) { + const char *szEnd = *sz; + ++*sz; + out.length = (ai_uint32)(szEnd - szStart); + ::memcpy(out.data, szStart, out.length); + } + } out.data[out.length] = '\0'; +} + // ------------------------------------------------------------------------------------------------ // .MD5MESH parsing function -MD5MeshParser::MD5MeshParser(SectionList &mSections) { +MD5MeshParser::MD5MeshParser(SectionArray &mSections) { ASSIMP_LOG_DEBUG("MD5MeshParser begin"); // now parse all sections - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { + for (SectionArray::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { if ((*iter).mName == "numMeshes") { mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str())); } else if ((*iter).mName == "numJoints") { @@ -288,14 +313,15 @@ MD5MeshParser::MD5MeshParser(SectionList &mSections) { BoneDesc &desc = mJoints.back(); const char *sz = elem.szStart; - AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); - AI_MD5_SKIP_SPACES(); + AI_MD5_PARSE_STRING_IN_QUOTATION(&sz, elem.end, desc.mName); + + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); // negative values, at least -1, is allowed here desc.mParentIndex = (int)strtol10(sz, &sz); - AI_MD5_READ_TRIPLE(desc.mPositionXYZ); - AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there + AI_MD5_READ_TRIPLE(desc.mPositionXYZ, &sz, elem.end, elem.iLineNumber); + AI_MD5_READ_TRIPLE(desc.mRotationQuat, &sz, elem.end, elem.iLineNumber); // normalized quaternion, so w is not there } } else if ((*iter).mName == "mesh") { mMeshes.emplace_back(); @@ -306,52 +332,52 @@ MD5MeshParser::MD5MeshParser(SectionList &mSections) { // shader attribute if (TokenMatch(sz, "shader", 6)) { - AI_MD5_SKIP_SPACES(); - AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mShader); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); + AI_MD5_PARSE_STRING_IN_QUOTATION(&sz, elem.end, desc.mShader); } // numverts attribute else if (TokenMatch(sz, "numverts", 8)) { - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); desc.mVertices.resize(strtoul10(sz)); } // numtris attribute else if (TokenMatch(sz, "numtris", 7)) { - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); desc.mFaces.resize(strtoul10(sz)); } // numweights attribute else if (TokenMatch(sz, "numweights", 10)) { - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); desc.mWeights.resize(strtoul10(sz)); } // vert attribute // "vert 0 ( 0.394531 0.513672 ) 0 1" else if (TokenMatch(sz, "vert", 4)) { - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); const unsigned int idx = ::strtoul10(sz, &sz); - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); if (idx >= desc.mVertices.size()) desc.mVertices.resize(idx + 1); VertexDesc &vert = desc.mVertices[idx]; if ('(' != *sz++) MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); sz = fast_atoreal_move(sz, (float &)vert.mUV.x); - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); sz = fast_atoreal_move(sz, (float &)vert.mUV.y); - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); if (')' != *sz++) MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber); - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); vert.mFirstWeight = ::strtoul10(sz, &sz); - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); vert.mNumWeights = ::strtoul10(sz, &sz); } // tri attribute // "tri 0 15 13 12" else if (TokenMatch(sz, "tri", 3)) { - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); const unsigned int idx = strtoul10(sz, &sz); if (idx >= desc.mFaces.size()) desc.mFaces.resize(idx + 1); @@ -359,24 +385,24 @@ MD5MeshParser::MD5MeshParser(SectionList &mSections) { aiFace &face = desc.mFaces[idx]; face.mIndices = new unsigned int[face.mNumIndices = 3]; for (unsigned int i = 0; i < 3; ++i) { - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); face.mIndices[i] = strtoul10(sz, &sz); } } // weight attribute // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )" else if (TokenMatch(sz, "weight", 6)) { - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); const unsigned int idx = strtoul10(sz, &sz); - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); if (idx >= desc.mWeights.size()) desc.mWeights.resize(idx + 1); WeightDesc &weight = desc.mWeights[idx]; weight.mBone = strtoul10(sz, &sz); - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); sz = fast_atoreal_move(sz, weight.mWeight); - AI_MD5_READ_TRIPLE(weight.vOffsetPosition); + AI_MD5_READ_TRIPLE(weight.vOffsetPosition, &sz, elem.end, elem.iLineNumber); } } } @@ -386,12 +412,12 @@ MD5MeshParser::MD5MeshParser(SectionList &mSections) { // ------------------------------------------------------------------------------------------------ // .MD5ANIM parsing function -MD5AnimParser::MD5AnimParser(SectionList &mSections) { +MD5AnimParser::MD5AnimParser(SectionArray &mSections) { ASSIMP_LOG_DEBUG("MD5AnimParser begin"); fFrameRate = 24.0f; mNumAnimatedComponents = UINT_MAX; - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { + for (SectionArray::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { if ((*iter).mName == "hierarchy") { // "sheath" 0 63 6 for (const auto &elem : (*iter).mElements) { @@ -399,18 +425,18 @@ MD5AnimParser::MD5AnimParser(SectionList &mSections) { AnimBoneDesc &desc = mAnimatedBones.back(); const char *sz = elem.szStart; - AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName); - AI_MD5_SKIP_SPACES(); + AI_MD5_PARSE_STRING_IN_QUOTATION(&sz, elem.end, desc.mName); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); // parent index - negative values are allowed (at least -1) desc.mParentIndex = ::strtol10(sz, &sz); // flags (highest is 2^6-1) - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); if (63 < (desc.iFlags = ::strtoul10(sz, &sz))) { MD5Parser::ReportWarning("Invalid flag combination in hierarchy section", elem.iLineNumber); } - AI_MD5_SKIP_SPACES(); + AI_MD5_SKIP_SPACES(& sz, elem.end, elem.iLineNumber); // index of the first animation keyframe component for this joint desc.iFirstKeyIndex = ::strtoul10(sz, &sz); @@ -423,8 +449,8 @@ MD5AnimParser::MD5AnimParser(SectionList &mSections) { mBaseFrames.emplace_back(); BaseFrameDesc &desc = mBaseFrames.back(); - AI_MD5_READ_TRIPLE(desc.vPositionXYZ); - AI_MD5_READ_TRIPLE(desc.vRotationQuat); + AI_MD5_READ_TRIPLE(desc.vPositionXYZ, &sz, elem.end, elem.iLineNumber); + AI_MD5_READ_TRIPLE(desc.vRotationQuat, &sz, elem.end, elem.iLineNumber); } } else if ((*iter).mName == "frame") { if (!(*iter).mGlobalValue.length()) { @@ -444,7 +470,7 @@ MD5AnimParser::MD5AnimParser(SectionList &mSections) { // now read all elements (continuous list of floats) for (const auto &elem : (*iter).mElements) { const char *sz = elem.szStart; - while (SkipSpacesAndLineEnd(&sz)) { + while (SkipSpacesAndLineEnd(&sz, elem.end)) { float f; sz = fast_atoreal_move(sz, f); desc.mValues.push_back(f); @@ -471,11 +497,11 @@ MD5AnimParser::MD5AnimParser(SectionList &mSections) { // ------------------------------------------------------------------------------------------------ // .MD5CAMERA parsing function -MD5CameraParser::MD5CameraParser(SectionList &mSections) { +MD5CameraParser::MD5CameraParser(SectionArray &mSections) { ASSIMP_LOG_DEBUG("MD5CameraParser begin"); fFrameRate = 24.0f; - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { + for (SectionArray::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) { if ((*iter).mName == "numFrames") { frames.reserve(strtoul10((*iter).mGlobalValue.c_str())); } else if ((*iter).mName == "frameRate") { @@ -492,9 +518,9 @@ MD5CameraParser::MD5CameraParser(SectionList &mSections) { frames.emplace_back(); CameraAnimFrameDesc &cur = frames.back(); - AI_MD5_READ_TRIPLE(cur.vPositionXYZ); - AI_MD5_READ_TRIPLE(cur.vRotationQuat); - AI_MD5_SKIP_SPACES(); + AI_MD5_READ_TRIPLE(cur.vPositionXYZ, &sz, elem.end, elem.iLineNumber); + AI_MD5_READ_TRIPLE(cur.vRotationQuat, &sz, elem.end, elem.iLineNumber); + AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); cur.fFOV = fast_atof(sz); } } diff --git a/code/AssetLib/MD5/MD5Parser.h b/code/AssetLib/MD5/MD5Parser.h index 9b29fbe85..75e3c22f2 100644 --- a/code/AssetLib/MD5/MD5Parser.h +++ b/code/AssetLib/MD5/MD5Parser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -68,12 +68,14 @@ struct Element { //! Elements are terminated with \0 char* szStart; + const char *end; + //! Original line number (can be used in error messages //! if a parsing error occurs) unsigned int iLineNumber; }; -using ElementList = std::vector; +using ElementArray = std::vector; // --------------------------------------------------------------------------- /** Represents a section of a MD5 file (such as the mesh or the joints section) @@ -86,7 +88,7 @@ struct Section { unsigned int iLineNumber; //! List of all elements which have been parsed in this section. - ElementList mElements; + ElementArray mElements; //! Name of the section std::string mName; @@ -96,7 +98,7 @@ struct Section { std::string mGlobalValue; }; -using SectionList = std::vector

; +using SectionArray = std::vector
; // --------------------------------------------------------------------------- /** Basic information about a joint @@ -132,7 +134,7 @@ struct BoneDesc : BaseJointDescription { unsigned int mMap; }; -using BoneList = std::vector; +using BoneArray = std::vector; // --------------------------------------------------------------------------- /** Represents a bone (joint) descriptor in a MD5Anim file @@ -145,7 +147,7 @@ struct AnimBoneDesc : BaseJointDescription { unsigned int iFirstKeyIndex; }; -using AnimBoneList = std::vector< AnimBoneDesc >; +using AnimBoneArray = std::vector< AnimBoneDesc >; // --------------------------------------------------------------------------- /** Represents a base frame descriptor in a MD5Anim file @@ -155,7 +157,7 @@ struct BaseFrameDesc { aiVector3D vRotationQuat; }; -using BaseFrameList = std::vector; +using BaseFrameArray = std::vector; // --------------------------------------------------------------------------- /** Represents a camera animation frame in a MDCamera file @@ -164,7 +166,7 @@ struct CameraAnimFrameDesc : BaseFrameDesc { float fFOV; }; -using CameraFrameList = std::vector; +using CameraFrameArray = std::vector; // --------------------------------------------------------------------------- /** Represents a frame descriptor in a MD5Anim file @@ -177,7 +179,7 @@ struct FrameDesc { std::vector< float > mValues; }; -using FrameList = std::vector; +using FrameArray = std::vector; // --------------------------------------------------------------------------- /** Represents a vertex descriptor in a MD5 file @@ -199,7 +201,7 @@ struct VertexDesc { unsigned int mNumWeights; }; -using VertexList = std::vector; +using VertexArray = std::vector; // --------------------------------------------------------------------------- /** Represents a vertex weight descriptor in a MD5 file @@ -216,27 +218,27 @@ struct WeightDesc { aiVector3D vOffsetPosition; }; -using WeightList = std::vector; -using FaceList = std::vector; +using WeightArray = std::vector; +using FaceArray = std::vector; // --------------------------------------------------------------------------- /** Represents a mesh in a MD5 file */ struct MeshDesc { //! Weights of the mesh - WeightList mWeights; + WeightArray mWeights; //! Vertices of the mesh - VertexList mVertices; + VertexArray mVertices; //! Faces of the mesh - FaceList mFaces; + FaceArray mFaces; //! Name of the shader (=texture) to be assigned to the mesh aiString mShader; }; -using MeshList = std::vector; +using MeshArray = std::vector; // --------------------------------------------------------------------------- // Convert a quaternion to its usual representation @@ -269,13 +271,13 @@ public: * * @param mSections List of file sections (output of MD5Parser) */ - explicit MD5MeshParser(SectionList& mSections); + explicit MD5MeshParser(SectionArray& mSections); //! List of all meshes - MeshList mMeshes; + MeshArray mMeshes; //! List of all joints - BoneList mJoints; + BoneArray mJoints; }; // remove this flag if you need to the bounding box data @@ -292,20 +294,20 @@ public: * * @param mSections List of file sections (output of MD5Parser) */ - explicit MD5AnimParser(SectionList& mSections); + explicit MD5AnimParser(SectionArray& mSections); //! Output frame rate float fFrameRate; //! List of animation bones - AnimBoneList mAnimatedBones; + AnimBoneArray mAnimatedBones; //! List of base frames - BaseFrameList mBaseFrames; + BaseFrameArray mBaseFrames; //! List of animation frames - FrameList mFrames; + FrameArray mFrames; //! Number of animated components unsigned int mNumAnimatedComponents; @@ -322,7 +324,7 @@ public: * * @param mSections List of file sections (output of MD5Parser) */ - explicit MD5CameraParser(SectionList& mSections); + explicit MD5CameraParser(SectionArray& mSections); //! Output frame rate float fFrameRate; @@ -331,7 +333,7 @@ public: std::vector cuts; //! Frames - CameraFrameList frames; + CameraFrameArray frames; }; // --------------------------------------------------------------------------- @@ -375,7 +377,7 @@ public: void ReportWarning (const char* warn); //! List of all sections which have been read - SectionList mSections; + SectionArray mSections; private: bool ParseSection(Section& out); @@ -388,7 +390,7 @@ private: private: char* buffer; - char* bufferEnd; + const char* bufferEnd; unsigned int fileSize; unsigned int lineNumber; }; @@ -406,7 +408,7 @@ inline void MD5Parser::ReportError(const char* error) { // ------------------------------------------------------------------- inline bool MD5Parser::SkipLine(const char* in, const char** out) { ++lineNumber; - return Assimp::SkipLine(in ,out); + return Assimp::SkipLine(in, out, bufferEnd); } // ------------------------------------------------------------------- @@ -450,7 +452,7 @@ inline bool MD5Parser::SkipSpacesAndLineEnd() { // ------------------------------------------------------------------- inline bool MD5Parser::SkipSpaces() { - return Assimp::SkipSpaces((const char**)&buffer); + return Assimp::SkipSpaces((const char**)&buffer, bufferEnd); } } // namespace Assimp diff --git a/code/AssetLib/MDC/MDCFileData.h b/code/AssetLib/MDC/MDCFileData.h index 36c589e91..4c5b4127c 100644 --- a/code/AssetLib/MDC/MDCFileData.h +++ b/code/AssetLib/MDC/MDCFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -61,7 +61,7 @@ http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf namespace Assimp { namespace MDC { -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" #define AI_MDC_MAGIC_NUMBER_BE AI_MAKE_MAGIC("CPDI") #define AI_MDC_MAGIC_NUMBER_LE AI_MAKE_MAGIC("IDPC") diff --git a/code/AssetLib/MDC/MDCLoader.cpp b/code/AssetLib/MDC/MDCLoader.cpp index 87247adec..c81ba67a6 100644 --- a/code/AssetLib/MDC/MDCLoader.cpp +++ b/code/AssetLib/MDC/MDCLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDC/MDCLoader.h b/code/AssetLib/MDC/MDCLoader.h index a1f8d9fc9..09ecc6865 100644 --- a/code/AssetLib/MDC/MDCLoader.h +++ b/code/AssetLib/MDC/MDCLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/HL1FileData.h b/code/AssetLib/MDL/HalfLife/HL1FileData.h index 28b1b2822..485f538ab 100644 --- a/code/AssetLib/MDL/HalfLife/HL1FileData.h +++ b/code/AssetLib/MDL/HalfLife/HL1FileData.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/HL1ImportDefinitions.h b/code/AssetLib/MDL/HalfLife/HL1ImportDefinitions.h index d412aeede..344574d24 100644 --- a/code/AssetLib/MDL/HalfLife/HL1ImportDefinitions.h +++ b/code/AssetLib/MDL/HalfLife/HL1ImportDefinitions.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/HL1ImportSettings.h b/code/AssetLib/MDL/HalfLife/HL1ImportSettings.h index 340ba2da5..52f98cb58 100644 --- a/code/AssetLib/MDL/HalfLife/HL1ImportSettings.h +++ b/code/AssetLib/MDL/HalfLife/HL1ImportSettings.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp index a8141fcc1..2d7f6a7c2 100644 --- a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp +++ b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h index 286b6e64c..ab5bb6942 100644 --- a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h +++ b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/HL1MeshTrivert.h b/code/AssetLib/MDL/HalfLife/HL1MeshTrivert.h index 4ef8a13ce..9c389a659 100644 --- a/code/AssetLib/MDL/HalfLife/HL1MeshTrivert.h +++ b/code/AssetLib/MDL/HalfLife/HL1MeshTrivert.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/HalfLifeMDLBaseHeader.h b/code/AssetLib/MDL/HalfLife/HalfLifeMDLBaseHeader.h index c7808c401..25ef27bca 100644 --- a/code/AssetLib/MDL/HalfLife/HalfLifeMDLBaseHeader.h +++ b/code/AssetLib/MDL/HalfLife/HalfLifeMDLBaseHeader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/LogFunctions.h b/code/AssetLib/MDL/HalfLife/LogFunctions.h index 003774dc1..c8cdf9b15 100644 --- a/code/AssetLib/MDL/HalfLife/LogFunctions.h +++ b/code/AssetLib/MDL/HalfLife/LogFunctions.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp b/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp index 3cca8c558..b79ec3613 100644 --- a/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp +++ b/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.h b/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.h index 73b6f9e74..cf190bc3b 100644 --- a/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.h +++ b/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/MDLDefaultColorMap.h b/code/AssetLib/MDL/MDLDefaultColorMap.h index 2eecac2dc..cbdc977ad 100644 --- a/code/AssetLib/MDL/MDLDefaultColorMap.h +++ b/code/AssetLib/MDL/MDLDefaultColorMap.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/MDLFileData.h b/code/AssetLib/MDL/MDLFileData.h index 7ec2afe9a..2aff59856 100644 --- a/code/AssetLib/MDL/MDLFileData.h +++ b/code/AssetLib/MDL/MDLFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -67,7 +67,7 @@ namespace Assimp { namespace MDL { // ------------------------------------------------------------------------------------- -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" // magic bytes used in Quake 1 MDL meshes #define AI_MDL_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDPO") diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index 2b14fe980..498e40b34 100644 --- a/code/AssetLib/MDL/MDLLoader.cpp +++ b/code/AssetLib/MDL/MDLLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -962,7 +962,7 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) { // no real name for our poor bone is specified :-( - pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, MAXLEN, + pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, AI_MAXLEN, "UnnamedBone_%i", iBone); } else { // Make sure we won't run over the buffer's end if there is no @@ -1567,7 +1567,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7() { } else { pcNode->mName.length = (ai_uint32)::strlen(szBuffer); } - ::strncpy(pcNode->mName.data, szBuffer, MAXLEN - 1); + ::strncpy(pcNode->mName.data, szBuffer, AI_MAXLEN - 1); ++p; } } diff --git a/code/AssetLib/MDL/MDLLoader.h b/code/AssetLib/MDL/MDLLoader.h index 333f7c8b1..f99f061ce 100644 --- a/code/AssetLib/MDL/MDLLoader.h +++ b/code/AssetLib/MDL/MDLLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MDL/MDLMaterialLoader.cpp b/code/AssetLib/MDL/MDLMaterialLoader.cpp index f8dafdb3e..f68f8e23e 100644 --- a/code/AssetLib/MDL/MDLMaterialLoader.cpp +++ b/code/AssetLib/MDL/MDLMaterialLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -494,7 +494,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( aiString szFile; const size_t iLen = strlen((const char *)szCurrent); - size_t iLen2 = iLen > (MAXLEN - 1) ? (MAXLEN - 1) : iLen; + size_t iLen2 = iLen > (AI_MAXLEN - 1) ? (AI_MAXLEN - 1) : iLen; memcpy(szFile.data, (const char *)szCurrent, iLen2); szFile.data[iLen2] = '\0'; szFile.length = static_cast(iLen2); @@ -730,7 +730,8 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7( // if an ASCII effect description (HLSL?) is contained in the file, // we can simply ignore it ... if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) { - int32_t iMe = *((int32_t *)szCurrent); + int32_t iMe = 0; + ::memcpy(&iMe, szCurrent, sizeof(int32_t)); AI_SWAP4(iMe); szCurrent += sizeof(char) * iMe + sizeof(int32_t); } diff --git a/code/AssetLib/MMD/MMDCpp14.h b/code/AssetLib/MMD/MMDCpp14.h index 10d376829..4a04bf69e 100644 --- a/code/AssetLib/MMD/MMDCpp14.h +++ b/code/AssetLib/MMD/MMDCpp14.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MMD/MMDImporter.cpp b/code/AssetLib/MMD/MMDImporter.cpp index b96d45c98..1e88cefd2 100644 --- a/code/AssetLib/MMD/MMDImporter.cpp +++ b/code/AssetLib/MMD/MMDImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MMD/MMDImporter.h b/code/AssetLib/MMD/MMDImporter.h index 1f584bf12..71fc534a4 100644 --- a/code/AssetLib/MMD/MMDImporter.h +++ b/code/AssetLib/MMD/MMDImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/MMD/MMDPmdParser.h b/code/AssetLib/MMD/MMDPmdParser.h index 23aaac555..b11c72f8d 100644 --- a/code/AssetLib/MMD/MMDPmdParser.h +++ b/code/AssetLib/MMD/MMDPmdParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MMD/MMDPmxParser.cpp b/code/AssetLib/MMD/MMDPmxParser.cpp index 6b04f02e9..5a3e61dcd 100644 --- a/code/AssetLib/MMD/MMDPmxParser.cpp +++ b/code/AssetLib/MMD/MMDPmxParser.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MMD/MMDPmxParser.h b/code/AssetLib/MMD/MMDPmxParser.h index 424fc725a..e90e554e7 100644 --- a/code/AssetLib/MMD/MMDPmxParser.h +++ b/code/AssetLib/MMD/MMDPmxParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MMD/MMDVmdParser.h b/code/AssetLib/MMD/MMDVmdParser.h index d5c7dedff..2ba9fb931 100644 --- a/code/AssetLib/MMD/MMDVmdParser.h +++ b/code/AssetLib/MMD/MMDVmdParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/MS3D/MS3DLoader.cpp b/code/AssetLib/MS3D/MS3DLoader.cpp index e0f0f8b5a..fac102f5f 100644 --- a/code/AssetLib/MS3D/MS3DLoader.cpp +++ b/code/AssetLib/MS3D/MS3DLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/AssetLib/MS3D/MS3DLoader.h b/code/AssetLib/MS3D/MS3DLoader.h index 3e25f1f59..5a28391eb 100644 --- a/code/AssetLib/MS3D/MS3DLoader.h +++ b/code/AssetLib/MS3D/MS3DLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/NDO/NDOLoader.cpp b/code/AssetLib/NDO/NDOLoader.cpp index 405438dfc..3515c14b4 100644 --- a/code/AssetLib/NDO/NDOLoader.cpp +++ b/code/AssetLib/NDO/NDOLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/NDO/NDOLoader.h b/code/AssetLib/NDO/NDOLoader.h index c4f127851..c3ab15230 100644 --- a/code/AssetLib/NDO/NDOLoader.h +++ b/code/AssetLib/NDO/NDOLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/NFF/NFFLoader.cpp b/code/AssetLib/NFF/NFFLoader.cpp index 78adc27bd..481a4bc19 100644 --- a/code/AssetLib/NFF/NFFLoader.cpp +++ b/code/AssetLib/NFF/NFFLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -85,7 +85,7 @@ const aiImporterDesc *NFFImporter::GetInfo() const { // ------------------------------------------------------------------------------------------------ #define AI_NFF_PARSE_FLOAT(f) \ - SkipSpaces(&sz); \ + SkipSpaces(&sz, lineEnd); \ if (!IsLineEnd(*sz)) sz = fast_atoreal_move(sz, (ai_real &)f); // ------------------------------------------------------------------------------------------------ @@ -111,7 +111,7 @@ const aiImporterDesc *NFFImporter::GetInfo() const { ASSIMP_LOG_WARN("NFF2: Unexpected EOF, can't read next token"); \ break; \ } \ - SkipSpaces(line, &sz); \ + SkipSpaces(line, &sz, lineEnd); \ } while (IsLineEnd(*sz)) // ------------------------------------------------------------------------------------------------ @@ -148,9 +148,9 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector &output, // No read the file line per line char line[4096]; - const char *sz; + const char *sz, *lineEnd = &line[2095]+1; while (GetNextLine(buffer, line)) { - SkipSpaces(line, &sz); + SkipSpaces(line, &sz, lineEnd); // 'version' defines the version of the file format if (TokenMatch(sz, "version", 7)) { @@ -198,18 +198,16 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector &output, // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void NFFImporter::InternReadFile(const std::string &pFile, - aiScene *pScene, IOSystem *pIOHandler) { - std::unique_ptr file(pIOHandler->Open(pFile, "rb")); - - // Check whether we can read from the file - if (!file) - throw DeadlyImportError("Failed to open NFF file ", pFile, "."); +void NFFImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr stream(pIOHandler->Open(file, "rb")); + if (!stream) { + throw DeadlyImportError("Failed to open NFF file ", file, "."); + } // allocate storage and copy the contents of the file to a memory buffer // (terminate it with zero) std::vector mBuffer2; - TextFileToBuffer(file.get(), mBuffer2); + TextFileToBuffer(stream.get(), mBuffer2); const char *buffer = &mBuffer2[0]; // mesh arrays - separate here to make the handling of the pointers below easier. @@ -219,8 +217,10 @@ void NFFImporter::InternReadFile(const std::string &pFile, std::vector meshesLocked; char line[4096]; + const char *lineEnd = &line[4096]; const char *sz; + // camera parameters aiVector3D camPos, camUp(0.f, 1.f, 0.f), camLookAt(0.f, 0.f, 1.f); ai_real angle = 45.f; @@ -265,7 +265,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, CommentRemover::RemoveLineComments("//", &mBuffer2[0]); while (GetNextLine(buffer, line)) { - SkipSpaces(line, &sz); + SkipSpaces(line, &sz, lineEnd); if (TokenMatch(sz, "version", 7)) { ASSIMP_LOG_INFO("NFF (Sense8) file format: ", sz); } else if (TokenMatch(sz, "viewpos", 7)) { @@ -295,7 +295,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, // material table - an external file if (TokenMatch(sz, "mtable", 6)) { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz3 = sz; while (!IsSpaceOrNewLine(*sz)) ++sz; @@ -316,12 +316,12 @@ void NFFImporter::InternReadFile(const std::string &pFile, std::string::size_type sepPos; if ((std::string::npos == (sepPos = path.find_last_of('\\')) || !sepPos) && (std::string::npos == (sepPos = path.find_last_of('/')) || !sepPos)) { - sepPos = pFile.find_last_of('\\'); + sepPos = file.find_last_of('\\'); if (std::string::npos == sepPos) { - sepPos = pFile.find_last_of('/'); + sepPos = file.find_last_of('/'); } if (std::string::npos != sepPos) { - path = pFile.substr(0, sepPos + 1) + path; + path = file.substr(0, sepPos + 1) + path; } } LoadNFF2MaterialTable(materialTable, path, pIOHandler); @@ -351,7 +351,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, // parse all other attributes in the line while (true) { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); if (IsLineEnd(*sz)) break; // color definition @@ -403,23 +403,20 @@ void NFFImporter::InternReadFile(const std::string &pFile, tempIdx.reserve(10); for (unsigned int i = 0; i < num; ++i) { AI_NFF2_GET_NEXT_TOKEN(); - SkipSpaces(line, &sz); + SkipSpaces(line, &sz, lineEnd); unsigned int numIdx = strtoul10(sz, &sz); // read all faces indices if (numIdx) { - // mesh.faces.push_back(numIdx); - // tempIdx.erase(tempIdx.begin(),tempIdx.end()); tempIdx.resize(numIdx); for (unsigned int a = 0; a < numIdx; ++a) { - SkipSpaces(sz, &sz); + SkipSpaces(sz, &sz, lineEnd); unsigned int m = strtoul10(sz, &sz); if (m >= (unsigned int)tempPositions.size()) { ASSIMP_LOG_ERROR("NFF2: Vertex index overflow"); m = 0; } - // mesh.vertices.push_back (tempPositions[idx]); tempIdx[a] = m; } } @@ -432,7 +429,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, shader.color = aiColor3D(1.f, 1.f, 1.f); aiColor4D c = aiColor4D(1.f, 1.f, 1.f, 1.f); while (true) { - SkipSpaces(sz, &sz); + SkipSpaces(sz, &sz, lineEnd); if (IsLineEnd(*sz)) break; // per-polygon colors @@ -510,7 +507,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, // Material ID? else if (!materialTable.empty() && TokenMatch(sz, "matid", 5)) { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); matIdx = strtoul10(sz, &sz); if (matIdx >= materialTable.size()) { ASSIMP_LOG_ERROR("NFF2: Material index overflow."); @@ -527,7 +524,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, shader.specular = mat.specular; shader.shininess = mat.shininess; } else - SkipToken(sz); + SkipToken(sz, lineEnd); } // search the list of all shaders we have for this object whether @@ -649,7 +646,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, sz = &line[1]; out = currentMesh; } - SkipSpaces(sz, &sz); + SkipSpaces(sz, &sz, lineEnd); unsigned int m = strtoul10(sz); // ---- flip the face order @@ -677,13 +674,13 @@ void NFFImporter::InternReadFile(const std::string &pFile, } if (out == currentMeshWithUVCoords) { // FIX: in one test file this wraps over multiple lines - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); if (IsLineEnd(*sz)) { GetNextLine(buffer, line); sz = line; } AI_NFF_PARSE_FLOAT(v.x); - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); if (IsLineEnd(*sz)) { GetNextLine(buffer, line); sz = line; @@ -717,7 +714,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, // if the next one is NOT a number we assume it is a texture file name // this feature is used by some NFF files on the internet and it has // been implemented as it can be really useful - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); if (!IsNumeric(*sz)) { // TODO: Support full file names with spaces and quotation marks ... const char *p = sz; @@ -731,10 +728,8 @@ void NFFImporter::InternReadFile(const std::string &pFile, } else { AI_NFF_PARSE_FLOAT(s.ambient); // optional } - } - // 'shader' - other way to specify a texture - else if (TokenMatch(sz, "shader", 6)) { - SkipSpaces(&sz); + } else if (TokenMatch(sz, "shader", 6)) { // 'shader' - other way to specify a texture + SkipSpaces(&sz, lineEnd); const char *old = sz; while (!IsSpaceOrNewLine(*sz)) ++sz; @@ -889,7 +884,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, } // 'tess' - tessellation else if (TokenMatch(sz, "tess", 4)) { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); iTesselation = strtoul10(sz); } // 'from' - camera position @@ -929,7 +924,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, // '' - comment else if ('#' == line[0]) { const char *space; - SkipSpaces(&line[1], &space); + SkipSpaces(&line[1], &space, lineEnd); if (!IsLineEnd(*space)) { ASSIMP_LOG_INFO(space); } diff --git a/code/AssetLib/NFF/NFFLoader.h b/code/AssetLib/NFF/NFFLoader.h index b402aec84..dfa6a882f 100644 --- a/code/AssetLib/NFF/NFFLoader.h +++ b/code/AssetLib/NFF/NFFLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/OFF/OFFLoader.cpp b/code/AssetLib/OFF/OFFLoader.cpp index ce8dfc2d4..566e3212e 100644 --- a/code/AssetLib/OFF/OFFLoader.cpp +++ b/code/AssetLib/OFF/OFFLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -84,10 +84,10 @@ const aiImporterDesc *OFFImporter::GetInfo() const { // skip blank space, lines and comments static void NextToken(const char **car, const char *end) { - SkipSpacesAndLineEnd(car); + SkipSpacesAndLineEnd(car, end); while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) { - SkipLine(car); - SkipSpacesAndLineEnd(car); + SkipLine(car, end); + SkipSpacesAndLineEnd(car, end); } } @@ -195,6 +195,7 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy char line[4096]; buffer = car; const char *sz = car; + const char *lineEnd = &line[4096]; // now read all vertex lines for (unsigned int i = 0; i < numVertices; ++i) { @@ -210,13 +211,13 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // stop at dimensions: this allows loading 1D or 2D coordinate vertices for (unsigned int dim = 0; dim < dimensions; ++dim) { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz = fast_atoreal_move(sz, *vec[dim]); } // if has homogeneous coordinate, divide others by this one if (hasHomogenous) { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); ai_real w = 1.; sz = fast_atoreal_move(sz, w); for (unsigned int dim = 0; dim < dimensions; ++dim) { @@ -227,11 +228,11 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // read optional normals if (hasNormals) { aiVector3D &n = mesh->mNormals[i]; - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz = fast_atoreal_move(sz, (ai_real &)n.x); - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz = fast_atoreal_move(sz, (ai_real &)n.y); - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); fast_atoreal_move(sz, (ai_real &)n.z); } @@ -241,22 +242,22 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // in theory should be testing type ! if (hasColors) { aiColor4D &c = mesh->mColors[0][i]; - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz = fast_atoreal_move(sz, (ai_real &)c.r); if (*sz != '#' && *sz != '\n' && *sz != '\r') { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz = fast_atoreal_move(sz, (ai_real &)c.g); } else { c.g = 0.; } if (*sz != '#' && *sz != '\n' && *sz != '\r') { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz = fast_atoreal_move(sz, (ai_real &)c.b); } else { c.b = 0.; } if (*sz != '#' && *sz != '\n' && *sz != '\r') { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz = fast_atoreal_move(sz, (ai_real &)c.a); } else { c.a = 1.; @@ -264,9 +265,9 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy } if (hasTexCoord) { aiVector3D &t = mesh->mTextureCoords[0][i]; - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); sz = fast_atoreal_move(sz, (ai_real &)t.x); - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); fast_atoreal_move(sz, (ai_real &)t.y); } } @@ -280,7 +281,7 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy } unsigned int idx; sz = line; - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); idx = strtoul10(sz, &sz); if (!idx || idx > 9) { ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); @@ -291,7 +292,7 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy faces->mNumIndices = idx; faces->mIndices = new unsigned int[faces->mNumIndices]; for (unsigned int m = 0; m < faces->mNumIndices; ++m) { - SkipSpaces(&sz); + SkipSpaces(&sz, lineEnd); idx = strtoul10(sz, &sz); if (idx >= numVertices) { ASSIMP_LOG_ERROR("OFF: Vertex index is out of range"); diff --git a/code/AssetLib/OFF/OFFLoader.h b/code/AssetLib/OFF/OFFLoader.h index b8577e507..02829d360 100644 --- a/code/AssetLib/OFF/OFFLoader.h +++ b/code/AssetLib/OFF/OFFLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Obj/ObjExporter.cpp b/code/AssetLib/Obj/ObjExporter.cpp index a5d8325fc..7c5c051f3 100644 --- a/code/AssetLib/Obj/ObjExporter.cpp +++ b/code/AssetLib/Obj/ObjExporter.cpp @@ -59,9 +59,9 @@ namespace Assimp { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp -void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { +void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* props) { // invoke the exporter - ObjExporter exporter(pFile, pScene); + ObjExporter exporter(pFile, pScene, false, props); if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); @@ -86,9 +86,9 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp -void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* ) { +void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* props) { // invoke the exporter - ObjExporter exporter(pFile, pScene, true); + ObjExporter exporter(pFile, pScene, true, props); if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); @@ -111,7 +111,7 @@ void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* p static const std::string MaterialExt = ".mtl"; // ------------------------------------------------------------------------------------------------ -ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl) +ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl, const ExportProperties* props) : filename(_filename) , pScene(pScene) , vn() @@ -130,7 +130,10 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt mOutputMat.imbue(l); mOutputMat.precision(ASSIMP_AI_REAL_TEXT_PRECISION); - WriteGeometryFile(noMtl); + WriteGeometryFile( + noMtl, + props == nullptr ? true : props->GetPropertyBool("bJoinIdenticalVertices", true) + ); if ( !noMtl ) { WriteMaterialFile(); } @@ -255,14 +258,14 @@ void ObjExporter::WriteMaterialFile() { } } -void ObjExporter::WriteGeometryFile(bool noMtl) { +void ObjExporter::WriteGeometryFile(bool noMtl, bool merge_identical_vertices) { WriteHeader(mOutput); if (!noMtl) mOutput << "mtllib " << GetMaterialLibName() << endl << endl; // collect mesh geometry aiMatrix4x4 mBase; - AddNode(pScene->mRootNode, mBase); + AddNode(pScene->mRootNode, mBase, merge_identical_vertices); // write vertex positions with colors, if any mVpMap.getKeys( vp ); @@ -330,7 +333,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { } // ------------------------------------------------------------------------------------------------ -void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { +void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices) { mMeshes.emplace_back(); MeshInstance& mesh = mMeshes.back(); @@ -362,13 +365,14 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 for(unsigned int a = 0; a < f.mNumIndices; ++a) { const unsigned int idx = f.mIndices[a]; + const unsigned int fi = merge_identical_vertices ? 0 : idx; aiVector3D vert = mat * m->mVertices[idx]; if ( nullptr != m->mColors[ 0 ] ) { aiColor4D col4 = m->mColors[ 0 ][ idx ]; - face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)}); + face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b), fi}); } else { - face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)}); + face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0), fi}); } if (m->mNormals) { @@ -388,21 +392,21 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 } // ------------------------------------------------------------------------------------------------ -void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) { +void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices) { const aiMatrix4x4& mAbs = mParent * nd->mTransformation; aiMesh *cm( nullptr ); for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { cm = pScene->mMeshes[nd->mMeshes[i]]; if (nullptr != cm) { - AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); + AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices); } else { - AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); + AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices); } } for(unsigned int i = 0; i < nd->mNumChildren; ++i) { - AddNode(nd->mChildren[i], mAbs); + AddNode(nd->mChildren[i], mAbs, merge_identical_vertices); } } diff --git a/code/AssetLib/Obj/ObjExporter.h b/code/AssetLib/Obj/ObjExporter.h index a64f38f74..4c92aa16f 100644 --- a/code/AssetLib/Obj/ObjExporter.h +++ b/code/AssetLib/Obj/ObjExporter.h @@ -51,6 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + struct aiScene; struct aiNode; struct aiMesh; @@ -63,7 +65,7 @@ namespace Assimp { class ObjExporter { public: /// Constructor for a specific scene to export - ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false); + ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false, const ExportProperties* props = nullptr); ~ObjExporter(); std::string GetMaterialLibName(); std::string GetMaterialLibFileName(); @@ -97,10 +99,10 @@ private: void WriteHeader(std::ostringstream& out); void WriteMaterialFile(); - void WriteGeometryFile(bool noMtl=false); + void WriteGeometryFile(bool noMtl=false, bool merge_identical_vertices = false); std::string GetMaterialName(unsigned int index); - void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat); - void AddNode(const aiNode* nd, const aiMatrix4x4& mParent); + void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices); + void AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices); private: std::string filename; @@ -109,6 +111,7 @@ private: struct vertexData { aiVector3D vp; aiColor3D vc; // OBJ does not support 4D color + uint32_t index = 0; }; std::vector vn, vt; @@ -133,7 +136,7 @@ private: if (a.vc.g > b.vc.g) return false; if (a.vc.b < b.vc.b) return true; if (a.vc.b > b.vc.b) return false; - return false; + return a.index < b.index; } }; diff --git a/code/AssetLib/Obj/ObjFileData.h b/code/AssetLib/Obj/ObjFileData.h index 22090e63e..3dc20c799 100644 --- a/code/AssetLib/Obj/ObjFileData.h +++ b/code/AssetLib/Obj/ObjFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Obj/ObjFileImporter.cpp b/code/AssetLib/Obj/ObjFileImporter.cpp index 339e90b06..e956f83d4 100644 --- a/code/AssetLib/Obj/ObjFileImporter.cpp +++ b/code/AssetLib/Obj/ObjFileImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Obj/ObjFileMtlImporter.cpp b/code/AssetLib/Obj/ObjFileMtlImporter.cpp index f8e3e1cde..effdf627f 100644 --- a/code/AssetLib/Obj/ObjFileMtlImporter.cpp +++ b/code/AssetLib/Obj/ObjFileMtlImporter.cpp @@ -343,7 +343,7 @@ void ObjFileMtlImporter::createMaterial() { } } - name = trim_whitespaces(name); + name = ai_trim(name); std::map::iterator it = m_pModel->mMaterialMap.find(name); if (m_pModel->mMaterialMap.end() == it) { diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index acb3f074c..fec1fe87b 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -52,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include namespace Assimp { @@ -64,6 +63,7 @@ ObjFileParser::ObjFileParser() : m_pModel(nullptr), m_uiLine(0), m_buffer(), + mEnd(&m_buffer[Buffersize]), m_pIO(nullptr), m_progress(nullptr), m_originalObjFileName() { @@ -97,8 +97,6 @@ ObjFileParser::ObjFileParser(IOStreamBuffer &streamBuffer, const std::stri parseFile(streamBuffer); } -ObjFileParser::~ObjFileParser() = default; - void ObjFileParser::setBuffer(std::vector &buffer) { m_DataIt = buffer.begin(); m_DataItEnd = buffer.end(); @@ -121,6 +119,7 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { while (streamBuffer.getNextDataLine(buffer, '\\')) { m_DataIt = buffer.begin(); m_DataItEnd = buffer.end(); + mEnd = &buffer[buffer.size() - 1] + 1; // Handle progress reporting const size_t filePos(streamBuffer.getFilePos()); @@ -130,7 +129,7 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { m_progress->UpdateFileRead(processed, progressTotal); } - // handle cstype section end (http://paulbourke.net/dataformats/obj/) + // handle c-stype section end (http://paulbourke.net/dataformats/obj/) if (insideCstype) { switch (*m_DataIt) { case 'e': { @@ -301,18 +300,19 @@ size_t ObjFileParser::getNumComponentsInDataDefinition() { } else if (IsLineEnd(*tmp)) { end_of_definition = true; } - if (!SkipSpaces(&tmp)) { + if (!SkipSpaces(&tmp, mEnd)) { break; } const bool isNum(IsNumeric(*tmp) || isNanOrInf(tmp)); - SkipToken(tmp); + SkipToken(tmp, mEnd); if (isNum) { ++numComponents; } - if (!SkipSpaces(&tmp)) { + if (!SkipSpaces(&tmp, mEnd)) { break; } } + return numComponents; } @@ -487,8 +487,9 @@ void ObjFileParser::getFace(aiPrimitiveType type) { ++iStep; } - if (iPos == 1 && !vt && vn) + if (iPos == 1 && !vt && vn) { iPos = 2; // skip texture coords for normals if there are no tex coords + } if (iVal > 0) { // Store parsed index @@ -576,14 +577,17 @@ void ObjFileParser::getMaterialDesc() { // Get name std::string strName(pStart, &(*m_DataIt)); - strName = trim_whitespaces(strName); - if (strName.empty()) + strName = ai_trim(strName); + if (strName.empty()) { skip = true; + } - // If the current mesh has the same material, we simply ignore that 'usemtl' command + // If the current mesh has the same material, we will ignore that 'usemtl' command // There is no need to create another object or even mesh here - if (m_pModel->mCurrentMaterial && m_pModel->mCurrentMaterial->MaterialName == aiString(strName)) { - skip = true; + if (!skip) { + if (m_pModel->mCurrentMaterial && m_pModel->mCurrentMaterial->MaterialName == aiString(strName)) { + skip = true; + } } if (!skip) { diff --git a/code/AssetLib/Obj/ObjFileParser.h b/code/AssetLib/Obj/ObjFileParser.h index 0ed724461..f3e149838 100644 --- a/code/AssetLib/Obj/ObjFileParser.h +++ b/code/AssetLib/Obj/ObjFileParser.h @@ -41,6 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef OBJ_FILEPARSER_H_INC #define OBJ_FILEPARSER_H_INC +#include "ObjFileData.h" + #include #include #include @@ -53,14 +55,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { -namespace ObjFile { -struct Model; -struct Object; -struct Material; -struct Point3; -struct Point2; -} // namespace ObjFile - class ObjFileImporter; class IOSystem; class ProgressHandler; @@ -79,7 +73,7 @@ public: /// @brief Constructor with data array. ObjFileParser(IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem *io, ProgressHandler *progress, const std::string &originalObjFileName); /// @brief Destructor - ~ObjFileParser(); + ~ObjFileParser() = default; /// @brief If you want to load in-core data. void setBuffer(std::vector &buffer); /// @brief Model getter. @@ -149,6 +143,7 @@ private: unsigned int m_uiLine; //! Helper buffer char m_buffer[Buffersize]; + const char *mEnd; /// Pointer to IO system instance. IOSystem *m_pIO; //! Pointer to progress handler diff --git a/code/AssetLib/Obj/ObjTools.h b/code/AssetLib/Obj/ObjTools.h index ca173de0a..ac5e119f2 100644 --- a/code/AssetLib/Obj/ObjTools.h +++ b/code/AssetLib/Obj/ObjTools.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -247,22 +247,6 @@ inline char_t getFloat(char_t it, char_t end, ai_real &value) { return it; } -/** - * @brief Will remove white-spaces for a string. - * @param[in] str The string to clean - * @return The trimmed string. - */ -template -inline string_type trim_whitespaces(string_type str) { - while (!str.empty() && IsSpace(str[0])) { - str.erase(0); - } - while (!str.empty() && IsSpace(str[str.length() - 1])) { - str.erase(str.length() - 1); - } - return str; -} - /** * @brief Checks for a line-end. * @param[in] it Current iterator in string. diff --git a/code/AssetLib/Ogre/OgreBinarySerializer.cpp b/code/AssetLib/Ogre/OgreBinarySerializer.cpp index 738e1181e..ee92785ef 100644 --- a/code/AssetLib/Ogre/OgreBinarySerializer.cpp +++ b/code/AssetLib/Ogre/OgreBinarySerializer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreBinarySerializer.h b/code/AssetLib/Ogre/OgreBinarySerializer.h index eb026ea70..7bba8b768 100644 --- a/code/AssetLib/Ogre/OgreBinarySerializer.h +++ b/code/AssetLib/Ogre/OgreBinarySerializer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreImporter.cpp b/code/AssetLib/Ogre/OgreImporter.cpp index 5bf6901a0..8e58179bc 100644 --- a/code/AssetLib/Ogre/OgreImporter.cpp +++ b/code/AssetLib/Ogre/OgreImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreImporter.h b/code/AssetLib/Ogre/OgreImporter.h index 3a72ae70e..2347956f2 100644 --- a/code/AssetLib/Ogre/OgreImporter.h +++ b/code/AssetLib/Ogre/OgreImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreMaterial.cpp b/code/AssetLib/Ogre/OgreMaterial.cpp index 0def59b79..d1244ada3 100644 --- a/code/AssetLib/Ogre/OgreMaterial.cpp +++ b/code/AssetLib/Ogre/OgreMaterial.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreParsingUtils.h b/code/AssetLib/Ogre/OgreParsingUtils.h index 60dd5cf76..2591644e3 100644 --- a/code/AssetLib/Ogre/OgreParsingUtils.h +++ b/code/AssetLib/Ogre/OgreParsingUtils.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreStructs.cpp b/code/AssetLib/Ogre/OgreStructs.cpp index ed8b9be79..29a8d768d 100644 --- a/code/AssetLib/Ogre/OgreStructs.cpp +++ b/code/AssetLib/Ogre/OgreStructs.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreStructs.h b/code/AssetLib/Ogre/OgreStructs.h index dcdf0670f..1ba8e840f 100644 --- a/code/AssetLib/Ogre/OgreStructs.h +++ b/code/AssetLib/Ogre/OgreStructs.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreXmlSerializer.cpp b/code/AssetLib/Ogre/OgreXmlSerializer.cpp index 8a1b88510..2eaa74c01 100644 --- a/code/AssetLib/Ogre/OgreXmlSerializer.cpp +++ b/code/AssetLib/Ogre/OgreXmlSerializer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ogre/OgreXmlSerializer.h b/code/AssetLib/Ogre/OgreXmlSerializer.h index 406681f55..c6f8e23a2 100644 --- a/code/AssetLib/Ogre/OgreXmlSerializer.h +++ b/code/AssetLib/Ogre/OgreXmlSerializer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/OpenGEX/OpenGEXExporter.cpp b/code/AssetLib/OpenGEX/OpenGEXExporter.cpp index f812d0ddb..cbea5f39b 100644 --- a/code/AssetLib/OpenGEX/OpenGEXExporter.cpp +++ b/code/AssetLib/OpenGEX/OpenGEXExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/OpenGEX/OpenGEXExporter.h b/code/AssetLib/OpenGEX/OpenGEXExporter.h index 8e31b9ae3..93e5ffc74 100644 --- a/code/AssetLib/OpenGEX/OpenGEXExporter.h +++ b/code/AssetLib/OpenGEX/OpenGEXExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp index 735f56755..20b2e77ac 100644 --- a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp +++ b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.h b/code/AssetLib/OpenGEX/OpenGEXImporter.h index 997d58af9..cf5773387 100644 --- a/code/AssetLib/OpenGEX/OpenGEXImporter.h +++ b/code/AssetLib/OpenGEX/OpenGEXImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/OpenGEX/OpenGEXStructs.h b/code/AssetLib/OpenGEX/OpenGEXStructs.h index 5f845483d..91b31a41a 100644 --- a/code/AssetLib/OpenGEX/OpenGEXStructs.h +++ b/code/AssetLib/OpenGEX/OpenGEXStructs.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ply/PlyExporter.cpp b/code/AssetLib/Ply/PlyExporter.cpp index 9453e0d4d..9c4b281b8 100644 --- a/code/AssetLib/Ply/PlyExporter.cpp +++ b/code/AssetLib/Ply/PlyExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -346,10 +346,22 @@ void PlyExporter::WriteMeshVertsBinary(const aiMesh* m, unsigned int components) for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) { if (m->HasVertexColors(c)) { - mOutput.write(reinterpret_cast(&m->mColors[c][i].r), 16); + unsigned char rgba[4] = { + static_cast(m->mColors[c][i].r * 255), + static_cast(m->mColors[c][i].g * 255), + static_cast(m->mColors[c][i].b * 255), + static_cast(m->mColors[c][i].a * 255) + }; + mOutput.write(reinterpret_cast(&rgba), 4); } else { - mOutput.write(reinterpret_cast(&defaultColor.r), 16); + unsigned char rgba[4] = { + static_cast(defaultColor.r * 255), + static_cast(defaultColor.g * 255), + static_cast(defaultColor.b * 255), + static_cast(defaultColor.a * 255) + }; + mOutput.write(reinterpret_cast(&rgba), 4); } } diff --git a/code/AssetLib/Ply/PlyExporter.h b/code/AssetLib/Ply/PlyExporter.h index ff3a54cb6..810626d69 100644 --- a/code/AssetLib/Ply/PlyExporter.h +++ b/code/AssetLib/Ply/PlyExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ply/PlyLoader.cpp b/code/AssetLib/Ply/PlyLoader.cpp index a747ba5cd..3e92339fb 100644 --- a/code/AssetLib/Ply/PlyLoader.cpp +++ b/code/AssetLib/Ply/PlyLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -159,7 +159,8 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy mBuffer = (unsigned char *)&mBuffer2[0]; char *szMe = (char *)&this->mBuffer[0]; - SkipSpacesAndLineEnd(szMe, (const char **)&szMe); + const char *end = &mBuffer2[0] + mBuffer2.size(); + SkipSpacesAndLineEnd(szMe, (const char **)&szMe, end); // determine the format of the file data and construct the aiMesh PLY::DOM sPlyDom; @@ -167,7 +168,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy if (TokenMatch(szMe, "format", 6)) { if (TokenMatch(szMe, "ascii", 5)) { - SkipLine(szMe, (const char **)&szMe); + SkipLine(szMe, (const char **)&szMe, end); if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) { if (mGeneratedMesh != nullptr) { delete (mGeneratedMesh); diff --git a/code/AssetLib/Ply/PlyLoader.h b/code/AssetLib/Ply/PlyLoader.h index f85445f91..048f40e3f 100644 --- a/code/AssetLib/Ply/PlyLoader.h +++ b/code/AssetLib/Ply/PlyLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Ply/PlyParser.cpp b/code/AssetLib/Ply/PlyParser.cpp index 662da805e..dbbabc03f 100644 --- a/code/AssetLib/Ply/PlyParser.cpp +++ b/code/AssetLib/Ply/PlyParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { // ------------------------------------------------------------------------------------------------ PLY::EDataType PLY::Property::ParseDataType(std::vector &buffer) { @@ -296,7 +296,7 @@ bool PLY::Element::ParseElement(IOStreamBuffer &streamBuffer, std::vector< return true; } - //parse the number of occurrences of this element + // parse the number of occurrences of this element const char *pCur = (char *)&buffer[0]; pOut->NumOccur = strtoul10(pCur, &pCur); @@ -321,13 +321,13 @@ bool PLY::Element::ParseElement(IOStreamBuffer &streamBuffer, std::vector< return true; } -// ------------------------------------------------------------------------------------------------ bool PLY::DOM::SkipSpaces(std::vector &buffer) { const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; + const char *end = pCur + buffer.size(); bool ret = false; if (pCur) { const char *szCur = pCur; - ret = Assimp::SkipSpaces(pCur, &pCur); + ret = Assimp::SkipSpaces(pCur, &pCur, end); uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; buffer.erase(buffer.begin(), buffer.begin() + iDiff); @@ -339,10 +339,11 @@ bool PLY::DOM::SkipSpaces(std::vector &buffer) { bool PLY::DOM::SkipLine(std::vector &buffer) { const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; + const char *end = pCur + buffer.size(); bool ret = false; if (pCur) { const char *szCur = pCur; - ret = Assimp::SkipLine(pCur, &pCur); + ret = Assimp::SkipLine(pCur, &pCur, end); uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; buffer.erase(buffer.begin(), buffer.begin() + iDiff); @@ -369,10 +370,11 @@ bool PLY::DOM::TokenMatch(std::vector &buffer, const char *token, unsigned bool PLY::DOM::SkipSpacesAndLineEnd(std::vector &buffer) { const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; + const char *end = pCur + buffer.size(); bool ret = false; if (pCur) { const char *szCur = pCur; - ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur); + ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur, end); uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; buffer.erase(buffer.begin(), buffer.begin() + iDiff); @@ -426,7 +428,7 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer &streamBuffer, std::vector } else { // ignore unknown header elements if (!streamBuffer.getNextLine(buffer)) - return false; + return false; } } @@ -446,7 +448,7 @@ bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer &streamBuffer, std std::vector::iterator a = alElementData.begin(); // parse all element instances - //construct vertices and faces + // construct vertices and faces for (; i != alElements.end(); ++i, ++a) { if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) { PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), nullptr, loader); @@ -528,7 +530,7 @@ bool PLY::DOM::ParseInstance(IOStreamBuffer &streamBuffer, DOM *p_pcOut, P return false; } - //get next line after header + // get next line after header streamBuffer.getNextLine(buffer); if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader)) { ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() failure"); @@ -558,23 +560,24 @@ bool PLY::ElementInstanceList::ParseInstanceList( } } else { const char *pCur = (const char *)&buffer[0]; + const char *end = pCur + buffer.size(); // be sure to have enough storage for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { if (p_pcOut) - PLY::ElementInstance::ParseInstance(pCur, pcElement, &p_pcOut->alInstances[i]); + PLY::ElementInstance::ParseInstance(pCur, end, pcElement, &p_pcOut->alInstances[i]); else { ElementInstance elt; - PLY::ElementInstance::ParseInstance(pCur, pcElement, &elt); + PLY::ElementInstance::ParseInstance(pCur, end, pcElement, &elt); // Create vertex or face if (pcElement->eSemantic == EEST_Vertex) { - //call loader instance from here + // call loader instance from here loader->LoadVertex(pcElement, &elt, i); } else if (pcElement->eSemantic == EEST_Face) { - //call loader instance from here + // call loader instance from here loader->LoadFace(pcElement, &elt, i); } else if (pcElement->eSemantic == EEST_TriStrip) { - //call loader instance from here + // call loader instance from here loader->LoadFace(pcElement, &elt, i); } } @@ -611,13 +614,13 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary( // Create vertex or face if (pcElement->eSemantic == EEST_Vertex) { - //call loader instance from here + // call loader instance from here loader->LoadVertex(pcElement, &elt, i); } else if (pcElement->eSemantic == EEST_Face) { - //call loader instance from here + // call loader instance from here loader->LoadFace(pcElement, &elt, i); } else if (pcElement->eSemantic == EEST_TriStrip) { - //call loader instance from here + // call loader instance from here loader->LoadFace(pcElement, &elt, i); } } @@ -626,7 +629,7 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary( } // ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstance::ParseInstance(const char *&pCur, +bool PLY::ElementInstance::ParseInstance(const char *&pCur, const char *end, const PLY::Element *pcElement, PLY::ElementInstance *p_pcOut) { ai_assert(nullptr != pcElement); @@ -638,7 +641,7 @@ bool PLY::ElementInstance::ParseInstance(const char *&pCur, std::vector::iterator i = p_pcOut->alProperties.begin(); std::vector::const_iterator a = pcElement->alProperties.begin(); for (; i != p_pcOut->alProperties.end(); ++i, ++a) { - if (!(PLY::PropertyInstance::ParseInstance(pCur, &(*a), &(*i)))) { + if (!(PLY::PropertyInstance::ParseInstance(pCur, end, &(*a), &(*i)))) { ASSIMP_LOG_WARN("Unable to parse property instance. " "Skipping this element instance"); @@ -678,13 +681,13 @@ bool PLY::ElementInstance::ParseInstanceBinary( } // ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseInstance(const char *&pCur, - const PLY::Property *prop, PLY::PropertyInstance *p_pcOut) { +bool PLY::PropertyInstance::ParseInstance(const char *&pCur, const char *end, const PLY::Property *prop, + PLY::PropertyInstance *p_pcOut) { ai_assert(nullptr != prop); ai_assert(nullptr != p_pcOut); // skip spaces at the beginning - if (!SkipSpaces(&pCur)) { + if (!SkipSpaces(&pCur, end)) { return false; } @@ -699,7 +702,7 @@ bool PLY::PropertyInstance::ParseInstance(const char *&pCur, // parse all list elements p_pcOut->avList.resize(iNum); for (unsigned int i = 0; i < iNum; ++i) { - if (!SkipSpaces(&pCur)) + if (!SkipSpaces(&pCur, end)) return false; PLY::PropertyInstance::ParseValue(pCur, prop->eType, &p_pcOut->avList[i]); @@ -711,7 +714,7 @@ bool PLY::PropertyInstance::ParseInstance(const char *&pCur, PLY::PropertyInstance::ParseValue(pCur, prop->eType, &v); p_pcOut->avList.push_back(v); } - SkipSpacesAndLineEnd(&pCur); + SkipSpacesAndLineEnd(&pCur, end); return true; } @@ -774,7 +777,7 @@ bool PLY::PropertyInstance::ParseValue(const char *&pCur, ai_assert(nullptr != pCur); ai_assert(nullptr != out); - //calc element size + // calc element size bool ret = true; switch (eType) { case EDT_UInt: @@ -824,7 +827,7 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer &streamBuffer, bool p_bBE) { ai_assert(nullptr != out); - //calc element size + // calc element size unsigned int lsize = 0; switch (eType) { case EDT_Char: @@ -852,11 +855,11 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer &streamBuffer, break; } - //read the next file block if needed + // read the next file block if needed if (bufferSize < lsize) { std::vector nbuffer; if (streamBuffer.getNextBlock(nbuffer)) { - //concat buffer contents + // concat buffer contents buffer = std::vector(buffer.end() - bufferSize, buffer.end()); buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end()); nbuffer.clear(); @@ -958,4 +961,6 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer &streamBuffer, return ret; } +} // namespace Assimp + #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER diff --git a/code/AssetLib/Ply/PlyParser.h b/code/AssetLib/Ply/PlyParser.h index 593791e92..fc6f346af 100644 --- a/code/AssetLib/Ply/PlyParser.h +++ b/code/AssetLib/Ply/PlyParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -324,7 +324,7 @@ public: // ------------------------------------------------------------------- //! Parse a property instance - static bool ParseInstance(const char* &pCur, + static bool ParseInstance(const char* &pCur, const char *end, const Property* prop, PropertyInstance* p_pcOut); // ------------------------------------------------------------------- @@ -364,7 +364,7 @@ public: // ------------------------------------------------------------------- //! Parse an element instance - static bool ParseInstance(const char* &pCur, + static bool ParseInstance(const char *&pCur, const char *end, const Element* pcElement, ElementInstance* p_pcOut); // ------------------------------------------------------------------- diff --git a/code/AssetLib/Q3BSP/Q3BSPFileData.h b/code/AssetLib/Q3BSP/Q3BSPFileData.h index 086cf7842..2d86ce564 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileData.h +++ b/code/AssetLib/Q3BSP/Q3BSPFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp index a82f29cf1..920279fce 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -588,7 +588,7 @@ bool Q3BSPFileImporter::importTextureFromArchive(const Q3BSP::Q3BSPModel *model, aiString name; name.data[0] = '*'; - name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(MAXLEN - 1), static_cast(mTextures.size())); + name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(AI_MAXLEN - 1), static_cast(mTextures.size())); archive->Close(pTextureStream); @@ -641,7 +641,7 @@ bool Q3BSPFileImporter::importLightmap(const Q3BSP::Q3BSPModel *pModel, aiScene aiString name; name.data[0] = '*'; - name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(MAXLEN - 1), static_cast(mTextures.size())); + name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast(AI_MAXLEN - 1), static_cast(mTextures.size())); pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_LIGHTMAP(1)); mTextures.push_back(pTexture); diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.h b/code/AssetLib/Q3BSP/Q3BSPFileImporter.h index 63d6edb21..b779c55a5 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.h +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Q3BSP/Q3BSPFileParser.cpp b/code/AssetLib/Q3BSP/Q3BSPFileParser.cpp index 910da5b36..c9c3d24cf 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileParser.cpp +++ b/code/AssetLib/Q3BSP/Q3BSPFileParser.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Q3BSP/Q3BSPFileParser.h b/code/AssetLib/Q3BSP/Q3BSPFileParser.h index 15cc751cc..de4d609e4 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileParser.h +++ b/code/AssetLib/Q3BSP/Q3BSPFileParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Q3D/Q3DLoader.cpp b/code/AssetLib/Q3D/Q3DLoader.cpp index b599ad8f2..84a508979 100644 --- a/code/AssetLib/Q3D/Q3DLoader.cpp +++ b/code/AssetLib/Q3D/Q3DLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -250,6 +250,10 @@ void Q3DImporter::InternReadFile(const std::string &pFile, c = stream.GetI1(); while (c) { mat.name.data[mat.name.length++] = c; + if (mat.name.length == AI_MAXLEN) { + ASSIMP_LOG_ERROR("String ouverflow detected, skipped material name parsing."); + break; + } c = stream.GetI1(); } diff --git a/code/AssetLib/Q3D/Q3DLoader.h b/code/AssetLib/Q3D/Q3DLoader.h index 54af86dc2..ed33ed7ca 100644 --- a/code/AssetLib/Q3D/Q3DLoader.h +++ b/code/AssetLib/Q3D/Q3DLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Raw/RawLoader.cpp b/code/AssetLib/Raw/RawLoader.cpp index 4c5f852b0..6c04680b8 100644 --- a/code/AssetLib/Raw/RawLoader.cpp +++ b/code/AssetLib/Raw/RawLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -104,11 +104,12 @@ void RAWImporter::InternReadFile(const std::string &pFile, // now read all lines char line[4096]; + const char *end = &line[4096]; while (GetNextLine(buffer, line)) { // if the line starts with a non-numeric identifier, it marks // the beginning of a new group const char *sz = line; - SkipSpaces(&sz); + SkipSpaces(&sz, end); if (IsLineEnd(*sz)) continue; if (!IsNumeric(*sz)) { const char *sz2 = sz; @@ -117,8 +118,8 @@ void RAWImporter::InternReadFile(const std::string &pFile, const unsigned int length = (unsigned int)(sz2 - sz); // find an existing group with this name - for (std::vector::iterator it = outGroups.begin(), end = outGroups.end(); - it != end; ++it) { + for (std::vector::iterator it = outGroups.begin(), endIt = outGroups.end(); + it != endIt; ++it) { if (length == (*it).name.length() && !::strcmp(sz, (*it).name.c_str())) { curGroup = it; sz2 = nullptr; @@ -134,7 +135,7 @@ void RAWImporter::InternReadFile(const std::string &pFile, float data[12]; unsigned int num; for (num = 0; num < 12; ++num) { - if (!SkipSpaces(&sz) || !IsNumeric(*sz)) break; + if (!SkipSpaces(&sz, end) || !IsNumeric(*sz)) break; sz = fast_atoreal_move(sz, data[num]); } if (num != 12 && num != 9) { diff --git a/code/AssetLib/Raw/RawLoader.h b/code/AssetLib/Raw/RawLoader.h index 83e4a9f1f..aa0fbdf81 100644 --- a/code/AssetLib/Raw/RawLoader.h +++ b/code/AssetLib/Raw/RawLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/SIB/SIBImporter.cpp b/code/AssetLib/SIB/SIBImporter.cpp index 840f74b7d..e55e67541 100644 --- a/code/AssetLib/SIB/SIBImporter.cpp +++ b/code/AssetLib/SIB/SIBImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/SIB/SIBImporter.h b/code/AssetLib/SIB/SIBImporter.h index 903c36561..9dd0c0095 100644 --- a/code/AssetLib/SIB/SIBImporter.h +++ b/code/AssetLib/SIB/SIBImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/SMD/SMDLoader.cpp b/code/AssetLib/SMD/SMDLoader.cpp index 4b63dd9d0..1eac5d934 100644 --- a/code/AssetLib/SMD/SMDLoader.cpp +++ b/code/AssetLib/SMD/SMDLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -82,8 +82,10 @@ static constexpr aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer SMDImporter::SMDImporter() : - configFrameID(), - pScene( nullptr ), + configFrameID(), + mBuffer(), + mEnd(nullptr), + pScene(nullptr), iFileSize( 0 ), iSmallestFrame( INT_MAX ), dLengthOfAnim( 0.0 ), @@ -92,9 +94,6 @@ SMDImporter::SMDImporter() : // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -SMDImporter::~SMDImporter() = default; // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. @@ -590,12 +589,12 @@ void SMDImporter::CreateOutputMaterials() { pScene->mMaterials[iMat] = pcMat; aiString szName; - szName.length = static_cast(ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat)); + szName.length = static_cast(ai_snprintf(szName.data, AI_MAXLEN, "Texture_%u", iMat)); pcMat->AddProperty(&szName,AI_MATKEY_NAME); if (aszTextures[iMat].length()) { - ::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1); + ::strncpy(szName.data, aszTextures[iMat].c_str(), AI_MAXLEN - 1); szName.length = static_cast( aszTextures[iMat].length() ); pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0)); } @@ -632,13 +631,13 @@ void SMDImporter::ParseFile() { // read line per line ... for ( ;; ) { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent, mEnd)) { break; } // "version \n", should be 1 for hl and hl2 SMD files if (TokenMatch(szCurrent,"version",7)) { - if(!SkipSpaces(szCurrent,&szCurrent)) break; + if(!SkipSpaces(szCurrent,&szCurrent, mEnd)) break; if (1 != strtoul10(szCurrent,&szCurrent)) { ASSIMP_LOG_WARN("SMD.version is not 1. This " "file format is not known. Continuing happily ..."); @@ -647,26 +646,26 @@ void SMDImporter::ParseFile() { } // "nodes\n" - Starts the node section if (TokenMatch(szCurrent,"nodes",5)) { - ParseNodesSection(szCurrent,&szCurrent); + ParseNodesSection(szCurrent, &szCurrent, mEnd); continue; } // "triangles\n" - Starts the triangle section if (TokenMatch(szCurrent,"triangles",9)) { - ParseTrianglesSection(szCurrent,&szCurrent); + ParseTrianglesSection(szCurrent, &szCurrent, mEnd); continue; } // "vertexanimation\n" - Starts the vertex animation section if (TokenMatch(szCurrent,"vertexanimation",15)) { bHasUVs = false; - ParseVASection(szCurrent,&szCurrent); + ParseVASection(szCurrent, &szCurrent, mEnd); continue; } // "skeleton\n" - Starts the skeleton section if (TokenMatch(szCurrent,"skeleton",8)) { - ParseSkeletonSection(szCurrent,&szCurrent); + ParseSkeletonSection(szCurrent, &szCurrent, mEnd); continue; } - SkipLine(szCurrent,&szCurrent); + SkipLine(szCurrent, &szCurrent, mEnd); } } @@ -683,6 +682,7 @@ void SMDImporter::ReadSmd(const std::string &pFile, IOSystem* pIOHandler) { // Allocate storage and copy the contents of the file to a memory buffer mBuffer.resize(iFileSize + 1); TextFileToBuffer(file.get(), mBuffer); + mEnd = &mBuffer[mBuffer.size() - 1] + 1; iSmallestFrame = INT_MAX; bHasUVs = true; @@ -723,26 +723,26 @@ unsigned int SMDImporter::GetTextureIndex(const std::string& filename) { // ------------------------------------------------------------------------------------------------ // Parse the nodes section of the file -void SMDImporter::ParseNodesSection(const char* szCurrent, const char** szCurrentOut) { +void SMDImporter::ParseNodesSection(const char* szCurrent, const char** szCurrentOut, const char *end) { for ( ;; ) { // "end\n" - Ends the nodes section - if (0 == ASSIMP_strincmp(szCurrent,"end",3) && IsSpaceOrNewLine(*(szCurrent+3))) { + if (0 == ASSIMP_strincmp(szCurrent, "end", 3) && IsSpaceOrNewLine(*(szCurrent+3))) { szCurrent += 4; break; } - ParseNodeInfo(szCurrent,&szCurrent); + ParseNodeInfo(szCurrent,&szCurrent, end); } - SkipSpacesAndLineEnd(szCurrent,&szCurrent); + SkipSpacesAndLineEnd(szCurrent, &szCurrent, end); *szCurrentOut = szCurrent; } // ------------------------------------------------------------------------------------------------ // Parse the triangles section of the file -void SMDImporter::ParseTrianglesSection(const char* szCurrent, const char** szCurrentOut) { +void SMDImporter::ParseTrianglesSection(const char *szCurrent, const char **szCurrentOut, const char *end) { // Parse a triangle, parse another triangle, parse the next triangle ... // and so on until we reach a token that looks quite similar to "end" for ( ;; ) { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent, end)) { break; } @@ -750,17 +750,17 @@ void SMDImporter::ParseTrianglesSection(const char* szCurrent, const char** szCu if (TokenMatch(szCurrent,"end",3)) { break; } - ParseTriangle(szCurrent,&szCurrent); + ParseTriangle(szCurrent,&szCurrent, end); } - SkipSpacesAndLineEnd(szCurrent,&szCurrent); + SkipSpacesAndLineEnd(szCurrent,&szCurrent, end); *szCurrentOut = szCurrent; } // ------------------------------------------------------------------------------------------------ // Parse the vertex animation section of the file -void SMDImporter::ParseVASection(const char* szCurrent, const char** szCurrentOut) { +void SMDImporter::ParseVASection(const char *szCurrent, const char **szCurrentOut, const char *end) { unsigned int iCurIndex = 0; for ( ;; ) { - if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent, end)) { break; } @@ -774,10 +774,10 @@ void SMDImporter::ParseVASection(const char* szCurrent, const char** szCurrentOu // NOTE: The doc says that time values COULD be negative ... // NOTE2: this is the shape key -> valve docs int iTime = 0; - if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime) { + if (!ParseSignedInt(szCurrent, &szCurrent, end, iTime) || configFrameID != (unsigned int)iTime) { break; } - SkipLine(szCurrent,&szCurrent); + SkipLine(szCurrent,&szCurrent, end); } else { if(0 == iCurIndex) { asTriangles.emplace_back(); @@ -785,7 +785,7 @@ void SMDImporter::ParseVASection(const char* szCurrent, const char** szCurrentOu if (++iCurIndex == 3) { iCurIndex = 0; } - ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true); + ParseVertex(szCurrent,&szCurrent, end, asTriangles.back().avVertices[iCurIndex],true); } } @@ -794,16 +794,16 @@ void SMDImporter::ParseVASection(const char* szCurrent, const char** szCurrentOu asTriangles.pop_back(); } - SkipSpacesAndLineEnd(szCurrent,&szCurrent); + SkipSpacesAndLineEnd(szCurrent,&szCurrent, end); *szCurrentOut = szCurrent; } // ------------------------------------------------------------------------------------------------ // Parse the skeleton section of the file -void SMDImporter::ParseSkeletonSection(const char* szCurrent, const char** szCurrentOut) { +void SMDImporter::ParseSkeletonSection(const char *szCurrent, const char **szCurrentOut, const char *end) { int iTime = 0; for ( ;; ) { - if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent, end)) { break; } @@ -811,15 +811,15 @@ void SMDImporter::ParseSkeletonSection(const char* szCurrent, const char** szCur if (TokenMatch(szCurrent,"end",3)) { break; } else if (TokenMatch(szCurrent,"time",4)) { - // "time \n" - Specifies the current animation frame - if(!ParseSignedInt(szCurrent,&szCurrent,iTime)) { + // "time \n" - Specifies the current animation frame + if (!ParseSignedInt(szCurrent, &szCurrent, end, iTime)) { break; } iSmallestFrame = std::min(iSmallestFrame,iTime); - SkipLine(szCurrent,&szCurrent); + SkipLine(szCurrent, &szCurrent, end); } else { - ParseSkeletonElement(szCurrent,&szCurrent,iTime); + ParseSkeletonElement(szCurrent, &szCurrent, end, iTime); } } *szCurrentOut = szCurrent; @@ -827,16 +827,16 @@ void SMDImporter::ParseSkeletonSection(const char* szCurrent, const char** szCur // ------------------------------------------------------------------------------------------------ #define SMDI_PARSE_RETURN { \ - SkipLine(szCurrent,&szCurrent); \ + SkipLine(szCurrent,&szCurrent, end); \ *szCurrentOut = szCurrent; \ return; \ } // ------------------------------------------------------------------------------------------------ // Parse a node line -void SMDImporter::ParseNodeInfo(const char* szCurrent, const char** szCurrentOut) { +void SMDImporter::ParseNodeInfo(const char *szCurrent, const char **szCurrentOut, const char *end) { unsigned int iBone = 0; - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - if ( !ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent)) { + SkipSpacesAndLineEnd(szCurrent, &szCurrent, end); + if ( !ParseUnsignedInt(szCurrent, &szCurrent, end, iBone) || !SkipSpaces(szCurrent,&szCurrent, end)) { throw DeadlyImportError("Unexpected EOF/EOL while parsing bone index"); } if (iBone == UINT_MAX) { @@ -877,7 +877,7 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent, const char** szCurrentOut szCurrent = szEnd; // the only negative bone parent index that could occur is -1 AFAIK - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent)) { + if(!ParseSignedInt(szCurrent, &szCurrent, end, (int&)bone.iParent)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone parent index. Assuming -1"); SMDI_PARSE_RETURN; } @@ -888,12 +888,12 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent, const char** szCurrentOut // ------------------------------------------------------------------------------------------------ // Parse a skeleton element -void SMDImporter::ParseSkeletonElement(const char* szCurrent, const char** szCurrentOut,int iTime) { +void SMDImporter::ParseSkeletonElement(const char *szCurrent, const char **szCurrentOut, const char *end, int iTime) { aiVector3D vPos; aiVector3D vRot; unsigned int iBone = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone)) { + if (!ParseUnsignedInt(szCurrent, &szCurrent, end, iBone)) { ASSIMP_LOG_ERROR("Unexpected EOF/EOL while parsing bone index"); SMDI_PARSE_RETURN; } @@ -907,27 +907,27 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent, const char** szCur SMD::Bone::Animation::MatrixKey& key = bone.sAnim.asKeys.back(); key.dTime = (double)iTime; - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vPos.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vPos.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vPos.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.z"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vRot.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vRot.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vRot.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.z"); SMDI_PARSE_RETURN; } @@ -947,11 +947,11 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent, const char** szCur // ------------------------------------------------------------------------------------------------ // Parse a triangle -void SMDImporter::ParseTriangle(const char* szCurrent, const char** szCurrentOut) { +void SMDImporter::ParseTriangle(const char *szCurrent, const char **szCurrentOut, const char *end) { asTriangles.emplace_back(); SMD::Face& face = asTriangles.back(); - if(!SkipSpaces(szCurrent,&szCurrent)) { + if(!SkipSpaces(szCurrent, &szCurrent, end)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing a triangle"); return; } @@ -963,19 +963,19 @@ void SMDImporter::ParseTriangle(const char* szCurrent, const char** szCurrentOut // ... and get the index that belongs to this file name face.iTexture = GetTextureIndex(std::string(szLast,(uintptr_t)szCurrent-(uintptr_t)szLast)); - SkipSpacesAndLineEnd(szCurrent,&szCurrent); + SkipSpacesAndLineEnd(szCurrent, &szCurrent, end); // load three vertices for (auto &avVertex : face.avVertices) { - ParseVertex(szCurrent,&szCurrent, avVertex); + ParseVertex(szCurrent, &szCurrent, end, avVertex); } *szCurrentOut = szCurrent; } // ------------------------------------------------------------------------------------------------ // Parse a float -bool SMDImporter::ParseFloat(const char* szCurrent, const char** szCurrentOut, float& out) { - if(!SkipSpaces(&szCurrent)) { +bool SMDImporter::ParseFloat(const char *szCurrent, const char **szCurrentOut, const char *end, float &out) { + if (!SkipSpaces(&szCurrent, end)) { return false; } @@ -985,8 +985,8 @@ bool SMDImporter::ParseFloat(const char* szCurrent, const char** szCurrentOut, f // ------------------------------------------------------------------------------------------------ // Parse an unsigned int -bool SMDImporter::ParseUnsignedInt(const char* szCurrent, const char** szCurrentOut, unsigned int& out) { - if(!SkipSpaces(&szCurrent)) { +bool SMDImporter::ParseUnsignedInt(const char *szCurrent, const char **szCurrentOut, const char *end, unsigned int &out) { + if(!SkipSpaces(&szCurrent, end)) { return false; } @@ -996,8 +996,8 @@ bool SMDImporter::ParseUnsignedInt(const char* szCurrent, const char** szCurrent // ------------------------------------------------------------------------------------------------ // Parse a signed int -bool SMDImporter::ParseSignedInt(const char* szCurrent, const char** szCurrentOut, int& out) { - if(!SkipSpaces(&szCurrent)) { +bool SMDImporter::ParseSignedInt(const char *szCurrent, const char **szCurrentOut, const char *end, int &out) { + if(!SkipSpaces(&szCurrent, end)) { return false; } @@ -1008,37 +1008,37 @@ bool SMDImporter::ParseSignedInt(const char* szCurrent, const char** szCurrentOu // ------------------------------------------------------------------------------------------------ // Parse a vertex void SMDImporter::ParseVertex(const char* szCurrent, - const char** szCurrentOut, SMD::Vertex& vertex, + const char **szCurrentOut, const char *end, SMD::Vertex &vertex, bool bVASection /*= false*/) { - if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent)) { - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - return ParseVertex(szCurrent,szCurrentOut,vertex,bVASection); + if (SkipSpaces(&szCurrent, end) && IsLineEnd(*szCurrent)) { + SkipSpacesAndLineEnd(szCurrent,&szCurrent, end); + return ParseVertex(szCurrent, szCurrentOut, end, vertex, bVASection); } - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode)) { + if(!ParseSignedInt(szCurrent, &szCurrent, end, (int&)vertex.iParentNode)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.parent"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vertex.pos.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vertex.pos.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vertex.pos.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.z"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x)) { + if(!ParseFloat(szCurrent,&szCurrent,end, (float&)vertex.nor.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y)) { + if(!ParseFloat(szCurrent,&szCurrent, end, (float&)vertex.nor.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vertex.nor.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.z"); SMDI_PARSE_RETURN; } @@ -1047,11 +1047,11 @@ void SMDImporter::ParseVertex(const char* szCurrent, SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vertex.uv.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y)) { + if(!ParseFloat(szCurrent, &szCurrent, end, (float&)vertex.uv.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.y"); SMDI_PARSE_RETURN; } @@ -1059,16 +1059,16 @@ void SMDImporter::ParseVertex(const char* szCurrent, // now read the number of bones affecting this vertex // all elements from now are fully optional, we don't need them unsigned int iSize = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize)) { + if(!ParseUnsignedInt(szCurrent, &szCurrent, end, iSize)) { SMDI_PARSE_RETURN; } vertex.aiBoneLinks.resize(iSize,std::pair(0,0.0f)); for (auto &aiBoneLink : vertex.aiBoneLinks) { - if(!ParseUnsignedInt(szCurrent,&szCurrent,aiBoneLink.first)) { + if(!ParseUnsignedInt(szCurrent, &szCurrent, end, aiBoneLink.first)) { SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,aiBoneLink.second)) { + if(!ParseFloat(szCurrent, &szCurrent, end, aiBoneLink.second)) { SMDI_PARSE_RETURN; } } @@ -1077,6 +1077,6 @@ void SMDImporter::ParseVertex(const char* szCurrent, SMDI_PARSE_RETURN; } -} +} // namespace Assimp #endif // !! ASSIMP_BUILD_NO_SMD_IMPORTER diff --git a/code/AssetLib/SMD/SMDLoader.h b/code/AssetLib/SMD/SMDLoader.h index adf80ba14..c2f2f0a49 100644 --- a/code/AssetLib/SMD/SMDLoader.h +++ b/code/AssetLib/SMD/SMDLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -162,7 +162,7 @@ struct Bone { class ASSIMP_API SMDImporter : public BaseImporter { public: SMDImporter(); - ~SMDImporter() override; + ~SMDImporter() override = default; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. @@ -206,7 +206,7 @@ protected: * the next section (or to EOF) */ void ParseTrianglesSection(const char* szCurrent, - const char** szCurrentOut); + const char **szCurrentOut, const char *end); // ------------------------------------------------------------------- /** Parse the vertex animation section in VTA files @@ -216,7 +216,7 @@ protected: * the next section (or to EOF) */ void ParseVASection(const char* szCurrent, - const char** szCurrentOut); + const char **szCurrentOu, const char *end); // ------------------------------------------------------------------- /** Parse the nodes section of the SMD file @@ -226,7 +226,7 @@ protected: * the next section (or to EOF) */ void ParseNodesSection(const char* szCurrent, - const char** szCurrentOut); + const char **szCurrentOut, const char *end); // ------------------------------------------------------------------- /** Parse the skeleton section of the SMD file @@ -236,7 +236,7 @@ protected: * the next section (or to EOF) */ void ParseSkeletonSection(const char* szCurrent, - const char** szCurrentOut); + const char **szCurrentOut, const char *end); // ------------------------------------------------------------------- /** Parse a single triangle in the SMD file @@ -245,8 +245,7 @@ protected: * \param szCurrentOut Receives the output cursor position */ void ParseTriangle(const char* szCurrent, - const char** szCurrentOut); - + const char **szCurrentOut, const char *end); // ------------------------------------------------------------------- /** Parse a single vertex in the SMD file @@ -256,7 +255,7 @@ protected: * \param vertex Vertex to be filled */ void ParseVertex(const char* szCurrent, - const char** szCurrentOut, SMD::Vertex& vertex, + const char **szCurrentOut, const char *end, SMD::Vertex &vertex, bool bVASection = false); // ------------------------------------------------------------------- @@ -271,32 +270,31 @@ protected: /** Parse a line in the skeleton section */ void ParseSkeletonElement(const char* szCurrent, - const char** szCurrentOut,int iTime); + const char **szCurrentOut, const char *end, int iTime); // ------------------------------------------------------------------- /** Parse a line in the nodes section */ void ParseNodeInfo(const char* szCurrent, - const char** szCurrentOut); - + const char **szCurrentOut, const char *end); // ------------------------------------------------------------------- /** Parse a floating-point value */ bool ParseFloat(const char* szCurrent, - const char** szCurrentOut, float& out); + const char **szCurrentOut, const char *end, float &out); // ------------------------------------------------------------------- /** Parse an unsigned integer. There may be no sign! */ bool ParseUnsignedInt(const char* szCurrent, - const char** szCurrentOut, unsigned int& out); + const char **szCurrentOut, const char *end, unsigned int &out); // ------------------------------------------------------------------- /** Parse a signed integer. Signs (+,-) are handled. */ bool ParseSignedInt(const char* szCurrent, - const char** szCurrentOut, int& out); + const char **szCurrentOut, const char *end, int &out); // ------------------------------------------------------------------- /** Fix invalid time values in the file @@ -304,7 +302,7 @@ protected: void FixTimeValues(); // ------------------------------------------------------------------- - /** Add all children of a bone as subnodes to a node + /** Add all children of a bone as sub-nodes to a node * \param pcNode Parent node * \param iParent Parent bone index */ @@ -329,17 +327,15 @@ protected: // ------------------------------------------------------------------- - inline bool SkipLine( const char* in, const char** out) - { - Assimp::SkipLine(in,out); + inline bool SkipLine( const char* in, const char** out, const char *end) { + Assimp::SkipLine(in, out, end); ++iLineNumber; return true; } // ------------------------------------------------------------------- - inline bool SkipSpacesAndLineEnd( const char* in, const char** out) - { + inline bool SkipSpacesAndLineEnd(const char *in, const char **out, const char *end) { ++iLineNumber; - return Assimp::SkipSpacesAndLineEnd(in,out); + return Assimp::SkipSpacesAndLineEnd(in, out, end); } private: @@ -349,6 +345,7 @@ private: /** Buffer to hold the loaded file */ std::vector mBuffer; + char *mEnd; /** Output scene to be filled */ diff --git a/code/AssetLib/STEPParser/STEPFileEncoding.cpp b/code/AssetLib/STEPParser/STEPFileEncoding.cpp index 92eb4f284..d7f512cbb 100644 --- a/code/AssetLib/STEPParser/STEPFileEncoding.cpp +++ b/code/AssetLib/STEPParser/STEPFileEncoding.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/STEPParser/STEPFileEncoding.h b/code/AssetLib/STEPParser/STEPFileEncoding.h index 950c9b3e2..6988a5822 100644 --- a/code/AssetLib/STEPParser/STEPFileEncoding.h +++ b/code/AssetLib/STEPParser/STEPFileEncoding.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/STEPParser/STEPFileReader.cpp b/code/AssetLib/STEPParser/STEPFileReader.cpp index 2bcfa1755..6bc8981f1 100644 --- a/code/AssetLib/STEPParser/STEPFileReader.cpp +++ b/code/AssetLib/STEPParser/STEPFileReader.cpp @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -40,9 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -/** @file STEPFileReader.cpp +/** + * @file STEPFileReader.cpp * @brief Implementation of the STEP file parser, which fills a - * STEP::DB with data read from a file. + * STEP::DB with data read from a file. */ #include "STEPFileReader.h" @@ -58,34 +58,28 @@ using namespace Assimp; namespace EXPRESS = STEP::EXPRESS; // ------------------------------------------------------------------------------------------------ -std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = std::string()) -{ +std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = std::string()) { return line == STEP::SyntaxError::LINE_NOT_SPECIFIED ? prefix+s : static_cast( (Formatter::format(),prefix,"(line ",line,") ",s) ); } // ------------------------------------------------------------------------------------------------ -std::string AddEntityID(const std::string& s,uint64_t entity /*= ENTITY_NOT_SPECIFIED*/, const std::string& prefix = std::string()) -{ +std::string AddEntityID(const std::string& s,uint64_t entity /*= ENTITY_NOT_SPECIFIED*/, const std::string& prefix = std::string()) { return entity == STEP::TypeError::ENTITY_NOT_SPECIFIED ? prefix+s : static_cast( (Formatter::format(),prefix,"(entity #",entity,") ",s)); } // ------------------------------------------------------------------------------------------------ -STEP::SyntaxError::SyntaxError (const std::string& s,uint64_t line /* = LINE_NOT_SPECIFIED */) -: DeadlyImportError(AddLineNumber(s,line)) -{ - +STEP::SyntaxError::SyntaxError (const std::string& s,uint64_t line) : DeadlyImportError(AddLineNumber(s,line)) { + // empty } // ------------------------------------------------------------------------------------------------ -STEP::TypeError::TypeError (const std::string& s,uint64_t entity /* = ENTITY_NOT_SPECIFIED */,uint64_t line /*= LINE_NOT_SPECIFIED*/) -: DeadlyImportError(AddLineNumber(AddEntityID(s,entity),line)) -{ - +STEP::TypeError::TypeError (const std::string& s,uint64_t entity, uint64_t line) : DeadlyImportError(AddLineNumber(AddEntityID(s,entity),line)) { + // empty } -static const char *ISO_Token = "ISO-10303-21;"; -static const char *FILE_SCHEMA_Token = "FILE_SCHEMA"; +static constexpr char ISO_Token[] = "ISO-10303-21;"; +static constexpr char FILE_SCHEMA_Token[] = "FILE_SCHEMA"; // ------------------------------------------------------------------------------------------------ STEP::DB* STEP::ReadFileHeader(std::shared_ptr stream) { std::shared_ptr reader = std::shared_ptr(new StreamReaderLE(std::move(stream))); @@ -110,8 +104,9 @@ STEP::DB* STEP::ReadFileHeader(std::shared_ptr stream) { if (s.substr(0,11) == FILE_SCHEMA_Token) { const char* sz = s.c_str()+11; - SkipSpaces(sz,&sz); - std::shared_ptr< const EXPRESS::DataType > schema = EXPRESS::DataType::Parse(sz); + const char *end = s.c_str() + s.size(); + SkipSpaces(sz,&sz, end); + std::shared_ptr< const EXPRESS::DataType > schema = EXPRESS::DataType::Parse(sz, end); // the file schema should be a regular list entity, although it usually contains exactly one entry // since the list itself is contained in a regular parameter list, we actually have @@ -304,10 +299,10 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, } // ------------------------------------------------------------------------------------------------ -std::shared_ptr EXPRESS::DataType::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= nullptr*/) +std::shared_ptr EXPRESS::DataType::Parse(const char*& inout, const char *end, uint64_t line, const EXPRESS::ConversionSchema* schema /*= nullptr*/) { const char* cur = inout; - SkipSpaces(&cur); + SkipSpaces(&cur, end); if (*cur == ',' || IsSpaceOrNewLine(*cur)) { throw STEP::SyntaxError("unexpected token, expected parameter",line); } @@ -325,7 +320,7 @@ std::shared_ptr EXPRESS::DataType::Parse(const char*& i std::transform(s.begin(),s.end(),s.begin(),&ai_tolower ); if (schema->IsKnownToken(s)) { for(cur = t+1;*cur++ != '(';); - std::shared_ptr dt = Parse(cur); + std::shared_ptr dt = Parse(cur, end); inout = *cur ? cur+1 : cur; return dt; } @@ -348,7 +343,7 @@ std::shared_ptr EXPRESS::DataType::Parse(const char*& i else if (*cur == '(' ) { // start of an aggregate, further parsing is done by the LIST factory constructor inout = cur; - return EXPRESS::LIST::Parse(inout,line,schema); + return EXPRESS::LIST::Parse(inout, end, line, schema); } else if (*cur == '.' ) { // enum (includes boolean) @@ -427,9 +422,10 @@ std::shared_ptr EXPRESS::DataType::Parse(const char*& i } // ------------------------------------------------------------------------------------------------ -std::shared_ptr EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= nullptr*/) { +std::shared_ptr EXPRESS::LIST::Parse(const char*& inout, const char *end, + uint64_t line, const EXPRESS::ConversionSchema* schema) { const std::shared_ptr list = std::make_shared(); - EXPRESS::LIST::MemberList& members = list->members; + EXPRESS::LIST::MemberList& cur_members = list->members; const char* cur = inout; if (*cur++ != '(') { @@ -442,19 +438,19 @@ std::shared_ptr EXPRESS::LIST::Parse(const char*& inout,uin count += (*c == ',' ? 1 : 0); } - members.reserve(count); + cur_members.reserve(count); for(;;++cur) { if (!*cur) { throw STEP::SyntaxError("unexpected end of line while reading list"); } - SkipSpaces(cur,&cur); + SkipSpaces(cur,&cur, end); if (*cur == ')') { break; } - members.push_back( EXPRESS::DataType::Parse(cur,line,schema)); - SkipSpaces(cur,&cur); + cur_members.push_back(EXPRESS::DataType::Parse(cur, end, line, schema)); + SkipSpaces(cur, &cur, end); if (*cur != ',') { if (*cur == ')') { @@ -464,7 +460,7 @@ std::shared_ptr EXPRESS::LIST::Parse(const char*& inout,uin } } - inout = cur+1; + inout = cur + 1; return list; } @@ -543,7 +539,8 @@ void STEP::LazyObject::LazyInit() const { } const char* acopy = args; - std::shared_ptr conv_args = EXPRESS::LIST::Parse(acopy,(uint64_t)STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema()); + const char *end = acopy + std::strlen(args); + std::shared_ptr conv_args = EXPRESS::LIST::Parse(acopy, end, (uint64_t)STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema()); delete[] args; args = nullptr; diff --git a/code/AssetLib/STEPParser/STEPFileReader.h b/code/AssetLib/STEPParser/STEPFileReader.h index 8a57937c0..85a7c5cb0 100644 --- a/code/AssetLib/STEPParser/STEPFileReader.h +++ b/code/AssetLib/STEPParser/STEPFileReader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -60,8 +60,7 @@ void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const* /// @brief Helper to read a file. template -inline -void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const (&arr)[N], const char* const (&arr2)[N2]) { +inline void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const (&arr)[N], const char* const (&arr2)[N2]) { return ReadFile(db,scheme,arr,N,arr2,N2); } diff --git a/code/AssetLib/STL/STLExporter.cpp b/code/AssetLib/STL/STLExporter.cpp index 9bbc2063f..0ff96296a 100644 --- a/code/AssetLib/STL/STLExporter.cpp +++ b/code/AssetLib/STL/STLExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/STL/STLExporter.h b/code/AssetLib/STL/STLExporter.h index 066dcfefd..b751e196c 100644 --- a/code/AssetLib/STL/STLExporter.h +++ b/code/AssetLib/STL/STLExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/STL/STLLoader.cpp b/code/AssetLib/STL/STLLoader.cpp index 269ee1467..3a9fc1b12 100644 --- a/code/AssetLib/STL/STLLoader.cpp +++ b/code/AssetLib/STL/STLLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -98,7 +98,7 @@ static bool IsAsciiSTL(const char *buffer, size_t fileSize) { const char *bufferEnd = buffer + fileSize; - if (!SkipSpaces(&buffer)) { + if (!SkipSpaces(&buffer, bufferEnd)) { return false; } @@ -244,11 +244,11 @@ void STLImporter::LoadASCIIFile(aiNode *root) { aiNode *node = new aiNode; node->mParent = root; nodes.push_back(node); - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); ai_assert(!IsLineEnd(sz)); sz += 5; // skip the "solid" - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); const char *szMe = sz; while (!IsSpaceOrNewLine(*sz)) { sz++; @@ -257,7 +257,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) { size_t temp = (size_t)(sz - szMe); // setup the name of the node if (temp) { - if (temp >= MAXLEN) { + if (temp >= AI_MAXLEN) { throw DeadlyImportError("STL: Node name too long"); } std::string name(szMe, temp); @@ -270,7 +270,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) { unsigned int faceVertexCounter = 3; for (;;) { // go to the next token - if (!SkipSpacesAndLineEnd(&sz)) { + if (!SkipSpacesAndLineEnd(&sz, bufferEnd)) { // seems we're finished although there was no end marker ASSIMP_LOG_WARN("STL: unexpected EOF. \'endsolid\' keyword was expected"); break; @@ -284,7 +284,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) { faceVertexCounter = 0; sz += 6; - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); if (strncmp(sz, "normal", 6)) { ASSIMP_LOG_WARN("STL: a facet normal vector was expected but not found"); } else { @@ -293,11 +293,11 @@ void STLImporter::LoadASCIIFile(aiNode *root) { } aiVector3D vn; sz += 7; - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); sz = fast_atoreal_move(sz, (ai_real &)vn.x); - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); sz = fast_atoreal_move(sz, (ai_real &)vn.y); - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); sz = fast_atoreal_move(sz, (ai_real &)vn.z); normalBuffer.emplace_back(vn); normalBuffer.emplace_back(vn); @@ -312,13 +312,13 @@ void STLImporter::LoadASCIIFile(aiNode *root) { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); } sz += 7; - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); positionBuffer.emplace_back(); aiVector3D *vn = &positionBuffer.back(); sz = fast_atoreal_move(sz, (ai_real &)vn->x); - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); sz = fast_atoreal_move(sz, (ai_real &)vn->y); - SkipSpaces(&sz); + SkipSpaces(&sz, bufferEnd); sz = fast_atoreal_move(sz, (ai_real &)vn->z); faceVertexCounter++; } @@ -326,7 +326,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) { do { ++sz; } while (!IsLineEnd(*sz)); - SkipSpacesAndLineEnd(&sz); + SkipSpacesAndLineEnd(&sz, bufferEnd); // finished! break; } else { // else skip the whole identifier diff --git a/code/AssetLib/STL/STLLoader.h b/code/AssetLib/STL/STLLoader.h index 0be6a95f0..cc6ab9607 100644 --- a/code/AssetLib/STL/STLLoader.h +++ b/code/AssetLib/STL/STLLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Step/STEPFile.h b/code/AssetLib/Step/STEPFile.h index 76a9370f5..1fd24b329 100644 --- a/code/AssetLib/Step/STEPFile.h +++ b/code/AssetLib/Step/STEPFile.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -82,8 +82,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // this is intended as stress test - by default, entities are evaluated // lazily and therefore not unless needed. -//#define ASSIMP_IFC_TEST - namespace Assimp { // ******************************************************************************** @@ -199,35 +197,27 @@ public: } public: - /** parse a variable from a string and set 'inout' to the character - * behind the last consumed character. An optional schema enables, - * if specified, automatic conversion of custom data types. - * - * @throw SyntaxError - */ - static std::shared_ptr Parse(const char *&inout, - uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, - const EXPRESS::ConversionSchema *schema = nullptr); + /// @brief Parse a variable from a string and set 'inout' to the character behind the last consumed character. + /// + /// An optional schema enables, if specified, automatic conversion of custom data types. + /// + /// @throw SyntaxError + static std::shared_ptr Parse(const char *&inout, const char *end, + uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, const EXPRESS::ConversionSchema *schema = nullptr); }; typedef DataType SELECT; typedef DataType LOGICAL; // ------------------------------------------------------------------------------- -/** Sentinel class to represent explicitly unset (optional) fields ($) */ +/// Sentinel class to represent explicitly unset (optional) fields ($) // ------------------------------------------------------------------------------- -class UNSET : public DataType { -public: -private: -}; +class UNSET : public DataType {}; // ------------------------------------------------------------------------------- -/** Sentinel class to represent explicitly derived fields (*) */ +/// Sentinel class to represent explicitly derived fields (*) // ------------------------------------------------------------------------------- -class ISDERIVED : public DataType { -public: -private: -}; +class ISDERIVED : public DataType {}; // ------------------------------------------------------------------------------- /** Shared implementation for some of the primitive data type, i.e. int, float @@ -304,7 +294,7 @@ public: public: /** @see DaraType::Parse */ - static std::shared_ptr Parse(const char *&inout, + static std::shared_ptr Parse(const char *&inout, const char *end, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, const EXPRESS::ConversionSchema *schema = nullptr); @@ -539,6 +529,7 @@ public: template const T &To() const { + return dynamic_cast(**this); } @@ -589,12 +580,12 @@ private: }; template -inline bool operator==(const std::shared_ptr &lo, T whatever) { +inline bool operator == (const std::shared_ptr &lo, T whatever) { return *lo == whatever; // XXX use std::forward if we have 0x } template -inline bool operator==(const std::pair> &lo, T whatever) { +inline bool operator == (const std::pair> &lo, T whatever) { return *(lo.second) == whatever; // XXX use std::forward if we have 0x } @@ -607,18 +598,30 @@ struct Lazy { Lazy(const LazyObject *obj = nullptr) : obj(obj) {} operator const T *() const { + if (obj == nullptr) { + throw TypeError("Obj type is nullptr."); + } return obj->ToPtr(); } operator const T &() const { + if (obj == nullptr) { + throw TypeError("Obj type is nullptr."); + } return obj->To(); } const T &operator*() const { + if (obj == nullptr) { + throw TypeError("Obj type is nullptr."); + } return obj->To(); } const T *operator->() const { + if (obj == nullptr) { + throw TypeError("Obj type is nullptr."); + } return &obj->To(); } diff --git a/code/AssetLib/Step/StepExporter.cpp b/code/AssetLib/Step/StepExporter.cpp index e13c9edab..2188ddfec 100644 --- a/code/AssetLib/Step/StepExporter.cpp +++ b/code/AssetLib/Step/StepExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Step/StepExporter.h b/code/AssetLib/Step/StepExporter.h index a02262659..9ae5fb820 100644 --- a/code/AssetLib/Step/StepExporter.h +++ b/code/AssetLib/Step/StepExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Terragen/TerragenLoader.cpp b/code/AssetLib/Terragen/TerragenLoader.cpp index b1870414c..150ebd011 100644 --- a/code/AssetLib/Terragen/TerragenLoader.cpp +++ b/code/AssetLib/Terragen/TerragenLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Terragen/TerragenLoader.h b/code/AssetLib/Terragen/TerragenLoader.h index 0c7b686e9..2d529464b 100644 --- a/code/AssetLib/Terragen/TerragenLoader.h +++ b/code/AssetLib/Terragen/TerragenLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/Unreal/UnrealLoader.cpp b/code/AssetLib/Unreal/UnrealLoader.cpp index 5f622da42..85b68b508 100644 --- a/code/AssetLib/Unreal/UnrealLoader.cpp +++ b/code/AssetLib/Unreal/UnrealLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -320,17 +320,18 @@ void UnrealImporter::InternReadFile(const std::string &pFile, std::vector _data; TextFileToBuffer(pb.get(), _data); const char *data = &_data[0]; + const char *end = &_data[_data.size() - 1] + 1; std::vector> tempTextures; // do a quick search in the UC file for some known, usually texture-related, tags for (; *data; ++data) { if (TokenMatchI(data, "#exec", 5)) { - SkipSpacesAndLineEnd(&data); + SkipSpacesAndLineEnd(&data, end); // #exec TEXTURE IMPORT [...] NAME=jjjjj [...] FILE=jjjj.pcx [...] if (TokenMatchI(data, "TEXTURE", 7)) { - SkipSpacesAndLineEnd(&data); + SkipSpacesAndLineEnd(&data, end); if (TokenMatchI(data, "IMPORT", 6)) { tempTextures.emplace_back(); @@ -348,14 +349,15 @@ void UnrealImporter::InternReadFile(const std::string &pFile, me.second = std::string(d, (size_t)(data - d)); } } - if (!me.first.length() || !me.second.length()) + if (!me.first.length() || !me.second.length()) { tempTextures.pop_back(); + } } } // #exec MESHMAP SETTEXTURE MESHMAP=box NUM=1 TEXTURE=Jtex1 // #exec MESHMAP SCALE MESHMAP=box X=0.1 Y=0.1 Z=0.2 else if (TokenMatchI(data, "MESHMAP", 7)) { - SkipSpacesAndLineEnd(&data); + SkipSpacesAndLineEnd(&data, end); if (TokenMatchI(data, "SETTEXTURE", 10)) { @@ -369,8 +371,7 @@ void UnrealImporter::InternReadFile(const std::string &pFile, } else if (!ASSIMP_strincmp(data, "TEXTURE=", 8)) { data += 8; const char *d = data; - for (; !IsSpaceOrNewLine(*data); ++data) - ; + for (; !IsSpaceOrNewLine(*data); ++data); me.second = std::string(d, (size_t)(data - d)); // try to find matching path names, doesn't care if we don't find them @@ -408,7 +409,7 @@ void UnrealImporter::InternReadFile(const std::string &pFile, // find out how many output meshes and materials we'll have and build material indices for (Unreal::Triangle &tri : triangles) { Unreal::TempMat mat(tri); - std::vector::iterator nt = std::find(materials.begin(), materials.end(), mat); + auto nt = std::find(materials.begin(), materials.end(), mat); if (nt == materials.end()) { // add material tri.matIndex = static_cast(materials.size()); @@ -451,7 +452,7 @@ void UnrealImporter::InternReadFile(const std::string &pFile, aiColor3D color(1.f, 1.f, 1.f); aiString s; - ::ai_snprintf(s.data, MAXLEN, "mat%u_tx%u_", i, materials[i].tex); + ::ai_snprintf(s.data, AI_MAXLEN, "mat%u_tx%u_", i, materials[i].tex); // set the two-sided flag if (materials[i].type == Unreal::MF_NORMAL_TS) { @@ -471,7 +472,7 @@ void UnrealImporter::InternReadFile(const std::string &pFile, // a special name for the weapon attachment point if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) { - s.length = ::ai_snprintf(s.data, MAXLEN, "$WeaponTag$"); + s.length = ::ai_snprintf(s.data, AI_MAXLEN, "$WeaponTag$"); color = aiColor3D(0.f, 0.f, 0.f); } diff --git a/code/AssetLib/Unreal/UnrealLoader.h b/code/AssetLib/Unreal/UnrealLoader.h index fda784cfb..b32a5fc74 100644 --- a/code/AssetLib/Unreal/UnrealLoader.h +++ b/code/AssetLib/Unreal/UnrealLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X/XFileExporter.cpp b/code/AssetLib/X/XFileExporter.cpp index f0b1608c1..15ecf9464 100644 --- a/code/AssetLib/X/XFileExporter.cpp +++ b/code/AssetLib/X/XFileExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X/XFileExporter.h b/code/AssetLib/X/XFileExporter.h index 1d9a5ae77..744944062 100644 --- a/code/AssetLib/X/XFileExporter.h +++ b/code/AssetLib/X/XFileExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X/XFileHelper.h b/code/AssetLib/X/XFileHelper.h index 4b95672f3..e3fff2b66 100644 --- a/code/AssetLib/X/XFileHelper.h +++ b/code/AssetLib/X/XFileHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X/XFileImporter.cpp b/code/AssetLib/X/XFileImporter.cpp index 00f44b34b..b386ff959 100644 --- a/code/AssetLib/X/XFileImporter.cpp +++ b/code/AssetLib/X/XFileImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -359,10 +359,18 @@ void XFileImporter::CreateMeshes(aiScene *pScene, aiNode *pNode, const std::vect // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex std::vector oldWeights(sourceMesh->mPositions.size(), 0.0); for (unsigned int d = 0; d < obone.mWeights.size(); ++d) { - const unsigned int boneIdx = obone.mWeights[d].mVertex; - if (boneIdx < obone.mWeights.size()) { + // TODO The conditional against boneIdx which was added in commit f844c33 + // TODO (https://github.com/assimp/assimp/commit/f844c3397d7726477ab0fdca8efd3df56c18366b) + // TODO causes massive breakage as detailed in: + // TODO https://github.com/assimp/assimp/issues/5332 + // TODO In cases like this unit tests are less useful, since the model still has + // TODO meshes, textures, animations etc. and asserts against these values may pass; + // TODO when touching importer code, it is crucial that developers also run manual, visual + // TODO checks to ensure there's no obvious breakage _before_ commiting to main branch + //const unsigned int boneIdx = obone.mWeights[d].mVertex; + //if (boneIdx < obone.mWeights.size()) { oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight; - } + //} } // collect all vertex weights that influence a vertex in the new mesh diff --git a/code/AssetLib/X/XFileImporter.h b/code/AssetLib/X/XFileImporter.h index 7be9cc8ec..cd741deec 100644 --- a/code/AssetLib/X/XFileImporter.h +++ b/code/AssetLib/X/XFileImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X/XFileParser.cpp b/code/AssetLib/X/XFileParser.cpp index 770c75a77..63c654b65 100644 --- a/code/AssetLib/X/XFileParser.cpp +++ b/code/AssetLib/X/XFileParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X/XFileParser.h b/code/AssetLib/X/XFileParser.h index 36eac2ada..32375511a 100644 --- a/code/AssetLib/X/XFileParser.h +++ b/code/AssetLib/X/XFileParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X3D/X3DImporter.cpp b/code/AssetLib/X3D/X3DImporter.cpp index eeb20b7c1..ada388080 100644 --- a/code/AssetLib/X3D/X3DImporter.cpp +++ b/code/AssetLib/X3D/X3DImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X3D/X3DImporter.hpp b/code/AssetLib/X3D/X3DImporter.hpp index 705a2472e..623160a38 100644 --- a/code/AssetLib/X3D/X3DImporter.hpp +++ b/code/AssetLib/X3D/X3DImporter.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp b/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp index 240ff14a8..b4562ace2 100644 --- a/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp +++ b/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/XGL/XGLLoader.cpp b/code/AssetLib/XGL/XGLLoader.cpp index 9efd5d628..614fac641 100644 --- a/code/AssetLib/XGL/XGLLoader.cpp +++ b/code/AssetLib/XGL/XGLLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -700,13 +700,14 @@ unsigned int XGLImporter::ReadIDAttr(XmlNode &node) { float XGLImporter::ReadFloat(XmlNode &node) { std::string v; XmlParser::getValueAsString(node, v); - const char *s = v.c_str(), *se; - if (!SkipSpaces(&s)) { + const char *s = v.c_str(); + const char *end = v.c_str() + v.size(); + if (!SkipSpaces(&s, end)) { LogError("unexpected EOL, failed to parse index element"); return 0.f; } - float t; - se = fast_atoreal_move(s, t); + float t{ 0.0f }; + const char *se = fast_atoreal_move(s, t); if (se == s) { LogError("failed to read float text"); return 0.f; @@ -720,7 +721,8 @@ unsigned int XGLImporter::ReadIndexFromText(XmlNode &node) { std::string v; XmlParser::getValueAsString(node, v); const char *s = v.c_str(); - if (!SkipSpaces(&s)) { + const char *end = v.c_str() + v.size(); + if (!SkipSpaces(&s, end)) { LogError("unexpected EOL, failed to parse index element"); return ErrorId; } @@ -741,16 +743,17 @@ aiVector2D XGLImporter::ReadVec2(XmlNode &node) { std::string val; XmlParser::getValueAsString(node, val); const char *s = val.c_str(); + const char *end = val.c_str() + val.size(); ai_real v[2] = {}; for (int i = 0; i < 2; ++i) { - if (!SkipSpaces(&s)) { + if (!SkipSpaces(&s, end)) { LogError("unexpected EOL, failed to parse vec2"); return vec; } v[i] = fast_atof(&s); - SkipSpaces(&s); + SkipSpaces(&s, end); if (i != 1 && *s != ',') { LogError("expected comma, failed to parse vec2"); return vec; @@ -769,14 +772,15 @@ aiVector3D XGLImporter::ReadVec3(XmlNode &node) { std::string v; XmlParser::getValueAsString(node, v); const char *s = v.c_str(); + const char *end = v.c_str() + v.size(); for (int i = 0; i < 3; ++i) { - if (!SkipSpaces(&s)) { + if (!SkipSpaces(&s, end)) { LogError("unexpected EOL, failed to parse vec3"); return vec; } vec[i] = fast_atof(&s); - SkipSpaces(&s); + SkipSpaces(&s, end); if (i != 2 && *s != ',') { LogError("expected comma, failed to parse vec3"); return vec; diff --git a/code/AssetLib/XGL/XGLLoader.h b/code/AssetLib/XGL/XGLLoader.h index f620561d1..9d39bc811 100644 --- a/code/AssetLib/XGL/XGLLoader.h +++ b/code/AssetLib/XGL/XGLLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index b5e6375ad..27dfae005 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF/glTFAsset.inl b/code/AssetLib/glTF/glTFAsset.inl index eddbf5706..5e554a31e 100644 --- a/code/AssetLib/glTF/glTFAsset.inl +++ b/code/AssetLib/glTF/glTFAsset.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF/glTFAssetWriter.h b/code/AssetLib/glTF/glTFAssetWriter.h index 6dbc42420..832c9e847 100644 --- a/code/AssetLib/glTF/glTFAssetWriter.h +++ b/code/AssetLib/glTF/glTFAssetWriter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF/glTFAssetWriter.inl b/code/AssetLib/glTF/glTFAssetWriter.inl index 2d80598ac..c0b8edfa2 100644 --- a/code/AssetLib/glTF/glTFAssetWriter.inl +++ b/code/AssetLib/glTF/glTFAssetWriter.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF/glTFCommon.cpp b/code/AssetLib/glTF/glTFCommon.cpp index fea680cd3..11e038fa3 100644 --- a/code/AssetLib/glTF/glTFCommon.cpp +++ b/code/AssetLib/glTF/glTFCommon.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF/glTFCommon.h b/code/AssetLib/glTF/glTFCommon.h index 187fbbdb5..e42d905ff 100644 --- a/code/AssetLib/glTF/glTFCommon.h +++ b/code/AssetLib/glTF/glTFCommon.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF/glTFExporter.cpp b/code/AssetLib/glTF/glTFExporter.cpp index 91d88f1ae..0cffda024 100644 --- a/code/AssetLib/glTF/glTFExporter.cpp +++ b/code/AssetLib/glTF/glTFExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include // Header files, standard library. #include @@ -113,6 +114,10 @@ glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiSc mAsset = std::make_shared(pIOSystem); + configEpsilon = mProperties->GetPropertyFloat( + AI_CONFIG_CHECK_IDENTITY_MATRIX_EPSILON, + (ai_real)AI_CONFIG_CHECK_IDENTITY_MATRIX_EPSILON_DEFAULT); + if (isBinary) { mAsset->SetAsBinary(); } @@ -824,7 +829,7 @@ unsigned int glTFExporter::ExportNodeHierarchy(const aiNode* n) { Ref node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node")); - if (!n->mTransformation.IsIdentity()) { + if (!n->mTransformation.IsIdentity(configEpsilon)) { node->matrix.isPresent = true; CopyValue(n->mTransformation, node->matrix.value); } @@ -851,7 +856,7 @@ unsigned int glTFExporter::ExportNode(const aiNode* n, Ref& parent) node->parent = parent; - if (!n->mTransformation.IsIdentity()) { + if (!n->mTransformation.IsIdentity(configEpsilon)) { node->matrix.isPresent = true; CopyValue(n->mTransformation, node->matrix.value); } diff --git a/code/AssetLib/glTF/glTFExporter.h b/code/AssetLib/glTF/glTFExporter.h index a52695402..adac06197 100644 --- a/code/AssetLib/glTF/glTFExporter.h +++ b/code/AssetLib/glTF/glTFExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include @@ -98,6 +99,8 @@ private: std::vector mBodyData; + ai_real configEpsilon; + void WriteBinaryData(IOStream *outfile, std::size_t sceneLength); void GetTexSampler(const aiMaterial *mat, glTF::TexProperty &prop); diff --git a/code/AssetLib/glTF/glTFImporter.cpp b/code/AssetLib/glTF/glTFImporter.cpp index cd8b7762d..2443205f3 100644 --- a/code/AssetLib/glTF/glTFImporter.cpp +++ b/code/AssetLib/glTF/glTFImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -109,7 +109,7 @@ inline void SetMaterialColorProperty(std::vector &embeddedTexIdxs, Asset & if (texIdx != -1) { // embedded // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) uri.data[0] = '*'; - uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); + uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx); } mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); @@ -242,7 +242,7 @@ void glTFImporter::ImportMeshes(glTF::Asset &r) { if (mesh.primitives.size() > 1) { ai_uint32 &len = aim->mName.length; aim->mName.data[len] = '-'; - len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); + len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(AI_MAXLEN - len - 1), p); } switch (prim.mode) { diff --git a/code/AssetLib/glTF/glTFImporter.h b/code/AssetLib/glTF/glTFImporter.h index 529da53cc..384299b1f 100644 --- a/code/AssetLib/glTF/glTFImporter.h +++ b/code/AssetLib/glTF/glTFImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 8d500b156..60ed368d1 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -547,7 +547,7 @@ struct BufferView : public Object { BufferViewTarget target; //! The target that the WebGL buffer should be bound to. void Read(Value &obj, Asset &r); - uint8_t *GetPointer(size_t accOffset); + uint8_t *GetPointerAndTailSize(size_t accOffset, size_t& outTailSize); }; //! A typed view into a BufferView. A BufferView contains raw binary data. @@ -629,7 +629,7 @@ struct Accessor : public Object { std::vector data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it. - void PopulateData(size_t numBytes, uint8_t *bytes); + void PopulateData(size_t numBytes, const uint8_t *bytes); void PatchData(unsigned int elementSize); }; }; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 61964d1b4..457fee8fa 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -785,12 +785,14 @@ inline void BufferView::Read(Value &obj, Asset &r) { } } -inline uint8_t *BufferView::GetPointer(size_t accOffset) { +inline uint8_t *BufferView::GetPointerAndTailSize(size_t accOffset, size_t& outTailSize) { if (!buffer) { + outTailSize = 0; return nullptr; } - uint8_t *basePtr = buffer->GetPointer(); + uint8_t * const basePtr = buffer->GetPointer(); if (!basePtr) { + outTailSize = 0; return nullptr; } @@ -799,17 +801,25 @@ inline uint8_t *BufferView::GetPointer(size_t accOffset) { const size_t begin = buffer->EncodedRegion_Current->Offset; const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length; if ((offset >= begin) && (offset < end)) { + outTailSize = end - offset; return &buffer->EncodedRegion_Current->DecodedData[offset - begin]; } } + if (offset >= buffer->byteLength) + { + outTailSize = 0; + return nullptr; + } + + outTailSize = buffer->byteLength - offset; return basePtr + offset; } // // struct Accessor // -inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) { +inline void Accessor::Sparse::PopulateData(size_t numBytes, const uint8_t *bytes) { if (bytes) { data.assign(bytes, bytes + numBytes); } else { @@ -818,11 +828,21 @@ inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) { } inline void Accessor::Sparse::PatchData(unsigned int elementSize) { - uint8_t *pIndices = indices->GetPointer(indicesByteOffset); + size_t indicesTailDataSize; + uint8_t *pIndices = indices->GetPointerAndTailSize(indicesByteOffset, indicesTailDataSize); const unsigned int indexSize = int(ComponentTypeSize(indicesType)); uint8_t *indicesEnd = pIndices + count * indexSize; - uint8_t *pValues = values->GetPointer(valuesByteOffset); + if ((uint64_t)indicesEnd > (uint64_t)pIndices + indicesTailDataSize) { + throw DeadlyImportError("Invalid sparse accessor. Indices outside allocated memory."); + } + + size_t valuesTailDataSize; + uint8_t* pValues = values->GetPointerAndTailSize(valuesByteOffset, valuesTailDataSize); + + if (elementSize * count > valuesTailDataSize) { + throw DeadlyImportError("Invalid sparse accessor. Indices outside allocated memory."); + } while (pIndices != indicesEnd) { size_t offset; switch (indicesType) { @@ -894,6 +914,9 @@ inline void Accessor::Read(Value &obj, Asset &r) { if (Value *indicesValue = FindObject(*sparseValue, "indices")) { //indices bufferView Value *indiceViewID = FindUInt(*indicesValue, "bufferView"); + if (!indiceViewID) { + throw DeadlyImportError("A bufferView value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); + } sparse->indices = r.bufferViews.Retrieve(indiceViewID->GetUint()); //indices byteOffset sparse->indicesByteOffset = MemberOrDefault(*indicesValue, "byteOffset", size_t(0)); @@ -909,6 +932,9 @@ inline void Accessor::Read(Value &obj, Asset &r) { if (Value *valuesValue = FindObject(*sparseValue, "values")) { //value bufferView Value *valueViewID = FindUInt(*valuesValue, "bufferView"); + if (!valueViewID) { + throw DeadlyImportError("A bufferView value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); + } sparse->values = r.bufferViews.Retrieve(valueViewID->GetUint()); //value byteOffset sparse->valuesByteOffset = MemberOrDefault(*valuesValue, "byteOffset", size_t(0)); @@ -918,8 +944,18 @@ inline void Accessor::Read(Value &obj, Asset &r) { const unsigned int elementSize = GetElementSize(); const size_t dataSize = count * elementSize; - sparse->PopulateData(dataSize, bufferView ? bufferView->GetPointer(byteOffset) : nullptr); - sparse->PatchData(elementSize); + if (bufferView) { + size_t bufferViewTailSize; + const uint8_t* bufferViewPointer = bufferView->GetPointerAndTailSize(byteOffset, bufferViewTailSize); + if (dataSize > bufferViewTailSize) { + throw DeadlyImportError("Invalid buffer when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); + } + sparse->PopulateData(dataSize, bufferViewPointer); + } + else { + sparse->PopulateData(dataSize, nullptr); + } + sparse->PatchData(elementSize); } } diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.h b/code/AssetLib/glTF2/glTF2AssetWriter.h index 4e5177b4e..f57b6558d 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.h +++ b/code/AssetLib/glTF2/glTF2AssetWriter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index bfd9135d3..17e29d8e7 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 17d162466..3df9d5dda 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include // Header files, standard library. #include @@ -90,6 +91,10 @@ glTF2Exporter::glTF2Exporter(const char *filename, IOSystem *pIOSystem, const ai // Always on as our triangulation process is aware of this type of encoding mAsset->extensionsUsed.FB_ngon_encoding = true; + configEpsilon = mProperties->GetPropertyFloat( + AI_CONFIG_CHECK_IDENTITY_MATRIX_EPSILON, + (ai_real)AI_CONFIG_CHECK_IDENTITY_MATRIX_EPSILON_DEFAULT); + if (isBinary) { mAsset->SetAsBinary(); } @@ -1455,7 +1460,7 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode *n) { node->name = n->mName.C_Str(); - if (!n->mTransformation.IsIdentity()) { + if (!n->mTransformation.IsIdentity(configEpsilon)) { node->matrix.isPresent = true; CopyValue(n->mTransformation, node->matrix.value); } @@ -1485,7 +1490,7 @@ unsigned int glTF2Exporter::ExportNode(const aiNode *n, Ref &parent) { ExportNodeExtras(n->mMetaData, node->extras); - if (!n->mTransformation.IsIdentity()) { + if (!n->mTransformation.IsIdentity(configEpsilon)) { if (mScene->mNumAnimations > 0 || (mProperties && mProperties->HasPropertyBool("GLTF2_NODE_IN_TRS"))) { aiQuaternion quaternion; n->mTransformation.Decompose(*reinterpret_cast(&node->scale.value), quaternion, *reinterpret_cast(&node->translation.value)); diff --git a/code/AssetLib/glTF2/glTF2Exporter.h b/code/AssetLib/glTF2/glTF2Exporter.h index 7bf57b567..27e187854 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.h +++ b/code/AssetLib/glTF2/glTF2Exporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include @@ -142,6 +143,7 @@ private: std::map mTexturesByPath; std::shared_ptr mAsset; std::vector mBodyData; + ai_real configEpsilon; }; } // namespace Assimp diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index e89baaf0d..eb158ce4f 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -92,7 +92,7 @@ static constexpr aiImporterDesc desc = { 0, 0, 0, - "gltf glb" + "gltf glb vrm" }; glTF2Importer::glTF2Importer() : @@ -106,7 +106,7 @@ const aiImporterDesc *glTF2Importer::GetInfo() const { bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(filename); - if (!checkSig && (extension != "gltf") && (extension != "glb")) { + if (!checkSig && (extension != "gltf") && (extension != "glb") && (extension != "vrm")) { return false; } @@ -161,7 +161,7 @@ static void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset if (texIdx != -1) { // embedded // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) uri.data[0] = '*'; - uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); + uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx); } mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); @@ -539,7 +539,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { if (mesh.primitives.size() > 1) { ai_uint32 &len = aim->mName.length; aim->mName.data[len] = '-'; - len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); + len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(AI_MAXLEN - len - 1), p); } switch (prim.mode) { diff --git a/code/AssetLib/glTF2/glTF2Importer.h b/code/AssetLib/glTF2/glTF2Importer.h index 2be42126c..68af0cb9c 100644 --- a/code/AssetLib/glTF2/glTF2Importer.h +++ b/code/AssetLib/glTF2/glTF2Importer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/CApi/AssimpCExport.cpp b/code/CApi/AssimpCExport.cpp index 21e40205c..99ad41ab7 100644 --- a/code/CApi/AssimpCExport.cpp +++ b/code/CApi/AssimpCExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/CApi/CInterfaceIOWrapper.cpp b/code/CApi/CInterfaceIOWrapper.cpp index f0e46cd08..84648482b 100644 --- a/code/CApi/CInterfaceIOWrapper.cpp +++ b/code/CApi/CInterfaceIOWrapper.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/CApi/CInterfaceIOWrapper.h b/code/CApi/CInterfaceIOWrapper.h index 28d4c3e75..34c4a7311 100644 --- a/code/CApi/CInterfaceIOWrapper.h +++ b/code/CApi/CInterfaceIOWrapper.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 9b0b964c0..f4c293672 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1,6 +1,6 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- -# Copyright (c) 2006-2022, assimp team +# Copyright (c) 2006-2024, assimp team # # All rights reserved. # @@ -42,7 +42,7 @@ # 3) Add libassimp using the file lists (eliminates duplication of file names between # source groups and library command) # -cmake_minimum_required( VERSION 3.10 ) +cmake_minimum_required( VERSION 3.22 ) SET( HEADER_PATH ../include/assimp ) if(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM) @@ -471,6 +471,14 @@ ADD_ASSIMP_IMPORTER( MDL AssetLib/MDL/HalfLife/UniqueNameGenerator.h ) +IF(((CMAKE_CXX_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU) AND CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13) + message(STATUS "GCC13 detected disabling \"-Warray-bounds and -Wstringop-overflow\" for" + " AssetLib/MDL/MDLLoader.cpp as it appears to be a false positive") + set_source_files_properties(AssetLib/MDL/MDLLoader.cpp PROPERTIES + COMPILE_FLAGS "-Wno-array-bounds -Wno-stringop-overflow" + ) +endif() + SET( MaterialSystem_SRCS Material/MaterialSystem.cpp Material/MaterialSystem.h @@ -503,6 +511,14 @@ ADD_ASSIMP_IMPORTER( OBJ AssetLib/Obj/ObjTools.h ) +IF(((CMAKE_CXX_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU) AND CMAKE_CXX_COMPILER_VERSION EQUAL 14) + message(STATUS "GCC14 detected disabling \"-Wmaybe-uninitialized\" for" + " AssetLib/Obj/ObjFileParser.cpp as it appears to be a false positive") + set_source_files_properties(AssetLib/Obj/ObjFileParser.cpp PROPERTIES + COMPILE_FLAGS "-Wno-maybe-uninitialized" + ) +endif() + ADD_ASSIMP_IMPORTER( OGRE AssetLib/Ogre/OgreImporter.h AssetLib/Ogre/OgreStructs.h @@ -1193,6 +1209,10 @@ ENDIF () TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp) +add_compile_options( + "$<$:-O0;-g3;-ggdb>" +) + IF (ASSIMP_WARNINGS_AS_ERRORS) MESSAGE(STATUS "Treating all warnings as errors (for assimp library only)") IF (MSVC) @@ -1282,7 +1302,7 @@ IF(ASSIMP_HUNTER_ENABLED) endif() if (ASSIMP_BUILD_DRACO) - target_link_libraries(assimp PUBLIC ${draco_LIBRARIES}) + target_link_libraries(assimp PRIVATE ${draco_LIBRARIES}) endif() ELSE() TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES}) @@ -1396,19 +1416,20 @@ IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC) TARGET_LINK_LIBRARIES(assimp rt) ENDIF () +IF(ASSIMP_INSTALL) + INSTALL( TARGETS assimp + EXPORT "${TARGETS_EXPORT_NAME}" + LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} + ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP-DEV_COMPONENT} + RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} + FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} + INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} + ) + INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev) + INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev) +ENDIF() -INSTALL( TARGETS assimp - EXPORT "${TARGETS_EXPORT_NAME}" - LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} - ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP-DEV_COMPONENT} - RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} - FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} - INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} -) -INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev) -INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev) - -if (ASSIMP_ANDROID_JNIIOSYSTEM) +if (ASSIMP_ANDROID_JNIIOSYSTEM AND ASSIMP_INSTALL) INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} COMPONENT assimp-dev) diff --git a/code/Common/AssertHandler.cpp b/code/Common/AssertHandler.cpp index 2fd4046ad..ee2d2b95c 100644 --- a/code/Common/AssertHandler.cpp +++ b/code/Common/AssertHandler.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/Assimp.cpp b/code/Common/Assimp.cpp index e3b39c349..bd1d6aedd 100644 --- a/code/Common/Assimp.cpp +++ b/code/Common/Assimp.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -233,8 +233,13 @@ const aiScene *aiImportFileFromMemoryWithProperties( unsigned int pFlags, const char *pHint, const aiPropertyStore *props) { - ai_assert(nullptr != pBuffer); - ai_assert(0 != pLength); + if (pBuffer == nullptr) { + return nullptr; + } + + if (pLength == 0u) { + return nullptr; + } const aiScene *scene = nullptr; ASSIMP_BEGIN_EXCEPTION_REGION(); diff --git a/code/Common/Base64.cpp b/code/Common/Base64.cpp index 65308f4fd..76f9b120e 100644 --- a/code/Common/Base64.cpp +++ b/code/Common/Base64.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index 9ef69a8e6..3a4c7c329 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -93,10 +93,6 @@ BaseImporter::BaseImporter() AI_NO_EXCEPT // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -BaseImporter::~BaseImporter() = default; - void BaseImporter::UpdateImporterScale(Importer *pImp) { ai_assert(pImp != nullptr); ai_assert(importerScale != 0.0); diff --git a/code/Common/BaseProcess.cpp b/code/Common/BaseProcess.cpp index 8ff7c98e9..560ee7b94 100644 --- a/code/Common/BaseProcess.cpp +++ b/code/Common/BaseProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -57,10 +57,6 @@ BaseProcess::BaseProcess() AI_NO_EXCEPT // empty } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -BaseProcess::~BaseProcess() = default; - // ------------------------------------------------------------------------------------------------ void BaseProcess::ExecuteOnScene(Importer *pImp) { ai_assert( nullptr != pImp ); diff --git a/code/Common/BaseProcess.h b/code/Common/BaseProcess.h index d2af4faa6..a945ad542 100644 --- a/code/Common/BaseProcess.h +++ b/code/Common/BaseProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -179,11 +179,11 @@ class ASSIMP_API BaseProcess { friend class Importer; public: - /** @brief onstructor to be privately used by Importer */ + /** @brief Constructor to be privately used by Importer */ BaseProcess() AI_NO_EXCEPT; - /** @brief Destructor, private as well */ - virtual ~BaseProcess(); + /** @brief Destructor */ + virtual ~BaseProcess() = default; // ------------------------------------------------------------------- /** diff --git a/code/Common/Bitmap.cpp b/code/Common/Bitmap.cpp index 65dfd1754..e6732c528 100644 --- a/code/Common/Bitmap.cpp +++ b/code/Common/Bitmap.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -148,8 +148,10 @@ void Bitmap::WriteData(aiTexture *texture, IOStream *file) { file->Write(pixel, mBytesPerPixel, 1); } - - file->Write(padding_data, padding, 1); + // When padding is 0, passing it as an argument will cause an assertion failure in DefaultIOStream::Write. + if (padding) { + file->Write(padding_data, padding, 1); + } } } diff --git a/code/Common/Compression.cpp b/code/Common/Compression.cpp index a6a7be7e4..091171771 100644 --- a/code/Common/Compression.cpp +++ b/code/Common/Compression.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/Compression.h b/code/Common/Compression.h index cfedc7409..0bec91bba 100644 --- a/code/Common/Compression.h +++ b/code/Common/Compression.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/CreateAnimMesh.cpp b/code/Common/CreateAnimMesh.cpp index 58f3d909d..467651587 100644 --- a/code/Common/CreateAnimMesh.cpp +++ b/code/Common/CreateAnimMesh.cpp @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- Copyright (C) 2016 The Qt Company Ltd. -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/DefaultIOStream.cpp b/code/Common/DefaultIOStream.cpp index f2c772187..e423eae4f 100644 --- a/code/Common/DefaultIOStream.cpp +++ b/code/Common/DefaultIOStream.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index a72627154..e74add55f 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/DefaultLogger.cpp b/code/Common/DefaultLogger.cpp index 5cb32d38f..828e326e2 100644 --- a/code/Common/DefaultLogger.cpp +++ b/code/Common/DefaultLogger.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/Common/DefaultProgressHandler.h b/code/Common/DefaultProgressHandler.h index ac1bb68db..2ace9e02a 100644 --- a/code/Common/DefaultProgressHandler.h +++ b/code/Common/DefaultProgressHandler.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/Exceptional.cpp b/code/Common/Exceptional.cpp index b25281a97..0629f716e 100644 --- a/code/Common/Exceptional.cpp +++ b/code/Common/Exceptional.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 0795da65c..4da055064 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/FileLogStream.h b/code/Common/FileLogStream.h index 334541485..f64f88f48 100644 --- a/code/Common/FileLogStream.h +++ b/code/Common/FileLogStream.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/IOSystem.cpp b/code/Common/IOSystem.cpp index 1e63827ba..aa91e9b49 100644 --- a/code/Common/IOSystem.cpp +++ b/code/Common/IOSystem.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index bdf64ac8f..284ad89cc 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/Importer.h b/code/Common/Importer.h index ab7e3a6b3..2da55f173 100644 --- a/code/Common/Importer.h +++ b/code/Common/Importer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -74,11 +74,11 @@ public: typedef unsigned int KeyType; // typedefs for our configuration maps. - typedef std::map IntPropertyMap; - typedef std::map FloatPropertyMap; - typedef std::map StringPropertyMap; - typedef std::map MatrixPropertyMap; - typedef std::map PointerPropertyMap; + using IntPropertyMap = std::map; + using FloatPropertyMap = std::map; + using StringPropertyMap = std::map; + using MatrixPropertyMap = std::map; + using PointerPropertyMap = std::map; /** IO handler to use for all file accesses. */ IOSystem* mIOHandler; @@ -128,10 +128,12 @@ public: /// The default class constructor. ImporterPimpl() AI_NO_EXCEPT; + + /// The class destructor. + ~ImporterPimpl() = default; }; -inline -ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT : +inline ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT : mIOHandler( nullptr ), mIsDefaultHandler( false ), mProgressHandler( nullptr ), diff --git a/code/Common/ImporterRegistry.cpp b/code/Common/ImporterRegistry.cpp index c67fee936..92a04e692 100644 --- a/code/Common/ImporterRegistry.cpp +++ b/code/Common/ImporterRegistry.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/Maybe.h b/code/Common/Maybe.h index 387c1bcaf..99b18b67c 100644 --- a/code/Common/Maybe.h +++ b/code/Common/Maybe.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/PolyTools.h b/code/Common/PolyTools.h index b53de8579..46ceb9d75 100644 --- a/code/Common/PolyTools.h +++ b/code/Common/PolyTools.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/PostStepRegistry.cpp b/code/Common/PostStepRegistry.cpp index de4f39083..fdf33fc40 100644 --- a/code/Common/PostStepRegistry.cpp +++ b/code/Common/PostStepRegistry.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/Common/RemoveComments.cpp b/code/Common/RemoveComments.cpp index 52dd37ff0..a6a472400 100644 --- a/code/Common/RemoveComments.cpp +++ b/code/Common/RemoveComments.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/SGSpatialSort.cpp b/code/Common/SGSpatialSort.cpp index 0ef1853c0..d24ecf1b4 100644 --- a/code/Common/SGSpatialSort.cpp +++ b/code/Common/SGSpatialSort.cpp @@ -3,9 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - - +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -50,16 +48,13 @@ the 3ds loader handling smooth groups correctly */ using namespace Assimp; // ------------------------------------------------------------------------------------------------ -SGSpatialSort::SGSpatialSort() -{ +SGSpatialSort::SGSpatialSort() { // define the reference plane. We choose some arbitrary vector away from all basic axes // in the hope that no model spreads all its vertices along this plane. mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f); mPlaneNormal.Normalize(); } -// ------------------------------------------------------------------------------------------------ -// Destructor -SGSpatialSort::~SGSpatialSort() = default; + // ------------------------------------------------------------------------------------------------ void SGSpatialSort::Add(const aiVector3D& vPosition, unsigned int index, unsigned int smoothingGroup) diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 0188f5dea..7954d4d01 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -78,7 +78,7 @@ inline void PrefixString(aiString &string, const char *prefix, unsigned int len) if (string.length >= 1 && string.data[0] == '$') return; - if (len + string.length >= MAXLEN - 1) { + if (len + string.length >= AI_MAXLEN - 1) { ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long"); ai_assert(false); return; @@ -408,7 +408,7 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vectormData. The size of mData is not guaranteed to be - // MAXLEN in size. + // AI_MAXLEN in size. aiString s(*(aiString *)prop->mData); if ('*' == s.data[0]) { // Offset the index and write it back .. diff --git a/code/Common/ScenePreprocessor.cpp b/code/Common/ScenePreprocessor.cpp index 18a257ad4..b4bbe9d67 100644 --- a/code/Common/ScenePreprocessor.cpp +++ b/code/Common/ScenePreprocessor.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/ScenePreprocessor.h b/code/Common/ScenePreprocessor.h index 49e06ed1c..6ffd7f8bd 100644 --- a/code/Common/ScenePreprocessor.h +++ b/code/Common/ScenePreprocessor.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -56,7 +55,7 @@ class ScenePreprocessorTest; namespace Assimp { // ---------------------------------------------------------------------------------- -/** ScenePreprocessor: Preprocess a scene before any post-processing +/** ScenePreprocessor: Pre-process a scene before any post-processing * steps are executed. * * The step computes data that needn't necessarily be provided by the @@ -79,6 +78,9 @@ public: ScenePreprocessor(aiScene *_scene) : scene(_scene) {} + /// @brief The class destructor. + ~ScenePreprocessor() = default; + // ---------------------------------------------------------------- /** Assign a (new) scene to the object. * diff --git a/code/Common/ScenePrivate.h b/code/Common/ScenePrivate.h index 3910db78c..b8c524aa2 100644 --- a/code/Common/ScenePrivate.h +++ b/code/Common/ScenePrivate.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/SkeletonMeshBuilder.cpp b/code/Common/SkeletonMeshBuilder.cpp index f3c8fb412..167652700 100644 --- a/code/Common/SkeletonMeshBuilder.cpp +++ b/code/Common/SkeletonMeshBuilder.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/SpatialSort.cpp b/code/Common/SpatialSort.cpp index c8c5c30ed..34cb3fb05 100644 --- a/code/Common/SpatialSort.cpp +++ b/code/Common/SpatialSort.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/StackAllocator.h b/code/Common/StackAllocator.h index 191010cac..a5d97c22d 100644 --- a/code/Common/StackAllocator.h +++ b/code/Common/StackAllocator.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -61,9 +61,10 @@ namespace Assimp { class StackAllocator { public: /// @brief Constructs the allocator - inline StackAllocator(); + StackAllocator(); + /// @brief Destructs the allocator and frees all memory - inline ~StackAllocator(); + ~StackAllocator(); // non copyable StackAllocator(const StackAllocator &) = delete; diff --git a/code/Common/StackAllocator.inl b/code/Common/StackAllocator.inl index 2c3164ca7..44f15edbc 100644 --- a/code/Common/StackAllocator.inl +++ b/code/Common/StackAllocator.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -41,11 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "StackAllocator.h" #include +#include using namespace Assimp; -inline StackAllocator::StackAllocator() { -} +inline StackAllocator::StackAllocator() : m_storageBlocks() {} inline StackAllocator::~StackAllocator() { FreeAll(); @@ -56,7 +56,7 @@ inline void *StackAllocator::Allocate(size_t byteSize) { { // double block size every time, up to maximum of g_maxBytesPerBlock. // Block size must be at least as large as byteSize, but we want to use this for small allocations anyway. - m_blockAllocationSize = std::max(std::min(m_blockAllocationSize * 2, g_maxBytesPerBlock), byteSize); + m_blockAllocationSize = std::max(std::min(m_blockAllocationSize * 2, g_maxBytesPerBlock), byteSize); uint8_t *data = new uint8_t[m_blockAllocationSize]; m_storageBlocks.emplace_back(data); m_subIndex = byteSize; diff --git a/code/Common/StandardShapes.cpp b/code/Common/StandardShapes.cpp index abf3c4839..4a967997e 100644 --- a/code/Common/StandardShapes.cpp +++ b/code/Common/StandardShapes.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/StbCommon.h b/code/Common/StbCommon.h index 5de2e176d..aef23ce17 100644 --- a/code/Common/StbCommon.h +++ b/code/Common/StbCommon.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -64,10 +64,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The list can be regenerated using the following: - cat | fgrep STBIDEF | fgrep '(' | sed -E 's/\*|\(.+//g' | \ - awk '{print "#define " $(NF) " assimp_" $(NF) }' | sort | uniq" + cat "path/to/stb/stb_image.h" | fgrep STBIDEF | fgrep '(' | sed -E 's/\*|\(.+//g' | \ + awk '{print "#define " $(NF) " assimp_" $(NF) }' | sort | uniq */ #define stbi_convert_iphone_png_to_rgb assimp_stbi_convert_iphone_png_to_rgb +#define stbi_convert_iphone_png_to_rgb_thread assimp_stbi_convert_iphone_png_to_rgb_thread #define stbi_convert_wchar_to_utf8 assimp_stbi_convert_wchar_to_utf8 #define stbi_failure_reason assimp_stbi_failure_reason #define stbi_hdr_to_ldr_gamma assimp_stbi_hdr_to_ldr_gamma @@ -87,22 +88,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define stbi_is_hdr_from_memory assimp_stbi_is_hdr_from_memory #define stbi_ldr_to_hdr_gamma assimp_stbi_ldr_to_hdr_gamma #define stbi_ldr_to_hdr_scale assimp_stbi_ldr_to_hdr_scale +#define stbi_load assimp_stbi_load #define stbi_load_16 assimp_stbi_load_16 #define stbi_load_16_from_callbacks assimp_stbi_load_16_from_callbacks #define stbi_load_16_from_memory assimp_stbi_load_16_from_memory -#define stbi_load assimp_stbi_load +#define stbi_load_from_callbacks assimp_stbi_load_from_callbacks +#define stbi_load_from_file assimp_stbi_load_from_file +#define stbi_load_from_file_16 assimp_stbi_load_from_file_16 +#define stbi_load_from_memory assimp_stbi_load_from_memory +#define stbi_load_gif_from_memory assimp_stbi_load_gif_from_memory #define stbi_loadf assimp_stbi_loadf #define stbi_loadf_from_callbacks assimp_stbi_loadf_from_callbacks #define stbi_loadf_from_file assimp_stbi_loadf_from_file #define stbi_loadf_from_memory assimp_stbi_loadf_from_memory -#define stbi_load_from_callbacks assimp_stbi_load_from_callbacks -#define stbi_load_from_file_16 assimp_stbi_load_from_file_16 -#define stbi_load_from_file assimp_stbi_load_from_file -#define stbi_load_from_memory assimp_stbi_load_from_memory -#define stbi_load_gif_from_memory assimp_stbi_load_gif_from_memory #define stbi_set_flip_vertically_on_load assimp_stbi_set_flip_vertically_on_load #define stbi_set_flip_vertically_on_load_thread assimp_stbi_set_flip_vertically_on_load_thread #define stbi_set_unpremultiply_on_load assimp_stbi_set_unpremultiply_on_load +#define stbi_set_unpremultiply_on_load_thread assimp_stbi_set_unpremultiply_on_load_thread #define stbi_zlib_decode_buffer assimp_stbi_zlib_decode_buffer #define stbi_zlib_decode_malloc assimp_stbi_zlib_decode_malloc #define stbi_zlib_decode_malloc_guesssize assimp_stbi_zlib_decode_malloc_guesssize diff --git a/code/Common/StdOStreamLogStream.h b/code/Common/StdOStreamLogStream.h index cc0e06263..683c87d5f 100644 --- a/code/Common/StdOStreamLogStream.h +++ b/code/Common/StdOStreamLogStream.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/Common/Subdivision.cpp b/code/Common/Subdivision.cpp index 3aea5d4c5..78c249807 100644 --- a/code/Common/Subdivision.cpp +++ b/code/Common/Subdivision.cpp @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -525,7 +524,11 @@ void CatmullClarkSubdivider::InternSubdivide( } } - ai_assert(adj[o] - moffsets[nidx].first < mp->mNumFaces); + if (mp == nullptr) { + continue; + } + + ai_assert(adj[o] - moffsets[nidx].first < mp->mNumFaces); const aiFace &f = mp->mFaces[adj[o] - moffsets[nidx].first]; bool haveit = false; diff --git a/code/Common/TargetAnimation.cpp b/code/Common/TargetAnimation.cpp index 5f6d9bad0..9ef4e5d6c 100644 --- a/code/Common/TargetAnimation.cpp +++ b/code/Common/TargetAnimation.cpp @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/TargetAnimation.h b/code/Common/TargetAnimation.h index 863406b94..116b55d2a 100644 --- a/code/Common/TargetAnimation.h +++ b/code/Common/TargetAnimation.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -119,12 +118,16 @@ private: * look-at target */ class TargetAnimationHelper { public: + /// @brief The class constructor. TargetAnimationHelper() : targetPositions(nullptr), objectPositions(nullptr) { // empty } + /// @brief The class destructor. + ~TargetAnimationHelper() = default; + // ------------------------------------------------------------------ /** Sets the target animation channel * diff --git a/code/Common/Version.cpp b/code/Common/Version.cpp index 1699b99d6..2fca44824 100644 --- a/code/Common/Version.cpp +++ b/code/Common/Version.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -44,15 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ScenePrivate.h" #include #include - -#include "revision.h" +#include // -------------------------------------------------------------------------------- // Legal information string - don't remove this. static constexpr char LEGAL_INFORMATION[] = "Open Asset Import Library (Assimp).\n" "A free C/C++ library to import various 3D file formats into applications\n\n" - "(c) 2006-2023, Assimp team\n" + "(c) 2006-2024, Assimp team\n" "License under the terms and conditions of the 3-clause BSD license\n" "https://www.assimp.org\n"; @@ -118,83 +117,3 @@ ASSIMP_API const char *aiGetBranchName() { return GitBranch; } -// ------------------------------------------------------------------------------------------------ -ASSIMP_API aiScene::aiScene() : - mFlags(0), - mRootNode(nullptr), - mNumMeshes(0), - mMeshes(nullptr), - mNumMaterials(0), - mMaterials(nullptr), - mNumAnimations(0), - mAnimations(nullptr), - mNumTextures(0), - mTextures(nullptr), - mNumLights(0), - mLights(nullptr), - mNumCameras(0), - mCameras(nullptr), - mMetaData(nullptr), - mName(), - mNumSkeletons(0), - mSkeletons(nullptr), - mPrivate(new Assimp::ScenePrivateData()) { - // empty -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API aiScene::~aiScene() { - // delete all sub-objects recursively - delete mRootNode; - - // To make sure we won't crash if the data is invalid it's - // much better to check whether both mNumXXX and mXXX are - // valid instead of relying on just one of them. - if (mNumMeshes && mMeshes) { - for (unsigned int a = 0; a < mNumMeshes; ++a) { - delete mMeshes[a]; - } - } - delete[] mMeshes; - - if (mNumMaterials && mMaterials) { - for (unsigned int a = 0; a < mNumMaterials; ++a) { - delete mMaterials[a]; - } - } - delete[] mMaterials; - - if (mNumAnimations && mAnimations) { - for (unsigned int a = 0; a < mNumAnimations; ++a) { - delete mAnimations[a]; - } - } - delete[] mAnimations; - - if (mNumTextures && mTextures) { - for (unsigned int a = 0; a < mNumTextures; ++a) { - delete mTextures[a]; - } - } - delete[] mTextures; - - if (mNumLights && mLights) { - for (unsigned int a = 0; a < mNumLights; ++a) { - delete mLights[a]; - } - } - delete[] mLights; - - if (mNumCameras && mCameras) { - for (unsigned int a = 0; a < mNumCameras; ++a) { - delete mCameras[a]; - } - } - delete[] mCameras; - - aiMetadata::Dealloc(mMetaData); - - delete[] mSkeletons; - - delete static_cast(mPrivate); -} diff --git a/code/Common/VertexTriangleAdjacency.cpp b/code/Common/VertexTriangleAdjacency.cpp index 555e3e386..616e7e797 100644 --- a/code/Common/VertexTriangleAdjacency.cpp +++ b/code/Common/VertexTriangleAdjacency.cpp @@ -3,9 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - - +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/VertexTriangleAdjacency.h b/code/Common/VertexTriangleAdjacency.h index 41d809450..20d3bd32c 100644 --- a/code/Common/VertexTriangleAdjacency.h +++ b/code/Common/VertexTriangleAdjacency.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/Win32DebugLogStream.h b/code/Common/Win32DebugLogStream.h index 34d849e83..f8bc017af 100644 --- a/code/Common/Win32DebugLogStream.h +++ b/code/Common/Win32DebugLogStream.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index 51a250810..23d7db15d 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -62,13 +62,13 @@ namespace Assimp { // ---------------------------------------------------------------- // A read-only file inside a ZIP -class ZipFile : public IOStream { +class ZipFile final : public IOStream { friend class ZipFileInfo; explicit ZipFile(std::string &filename, size_t size); public: std::string m_Filename; - virtual ~ZipFile() override; + ~ZipFile() override = default; // IOStream interface size_t Read(void *pvBuffer, size_t pSize, size_t pCount) override; @@ -89,6 +89,8 @@ private: // Wraps an existing Assimp::IOSystem for unzip class IOSystem2Unzip { public: + IOSystem2Unzip() = default; + ~IOSystem2Unzip() = default; static voidpf open(voidpf opaque, const char *filename, int mode); static voidpf opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode); static uLong read(voidpf opaque, voidpf stream, void *buf, uLong size); @@ -100,6 +102,7 @@ public: static zlib_filefunc_def get(IOSystem *pIOHandler); }; +// ---------------------------------------------------------------- voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) { IOSystem *io_system = reinterpret_cast(opaque); @@ -119,6 +122,7 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) { return (voidpf)io_system->Open(filename, mode_fopen); } +// ---------------------------------------------------------------- voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) { ZipFile *io_stream = (ZipFile *)stream; voidpf ret = nullptr; @@ -141,24 +145,28 @@ voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_di return ret; } +// ---------------------------------------------------------------- uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void *buf, uLong size) { IOStream *io_stream = (IOStream *)stream; return static_cast(io_stream->Read(buf, 1, size)); } +// ---------------------------------------------------------------- uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void *buf, uLong size) { IOStream *io_stream = (IOStream *)stream; return static_cast(io_stream->Write(buf, 1, size)); } +// ---------------------------------------------------------------- long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) { IOStream *io_stream = (IOStream *)stream; return static_cast(io_stream->Tell()); } +// ---------------------------------------------------------------- long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) { IOStream *io_stream = (IOStream *)stream; @@ -179,6 +187,7 @@ long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int or return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1); } +// ---------------------------------------------------------------- int IOSystem2Unzip::close(voidpf opaque, voidpf stream) { IOSystem *io_system = (IOSystem *)opaque; IOStream *io_stream = (IOStream *)stream; @@ -188,10 +197,12 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) { return 0; } +// ---------------------------------------------------------------- int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) { return 0; } +// ---------------------------------------------------------------- zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) { zlib_filefunc_def mapping; @@ -213,9 +224,10 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) { // ---------------------------------------------------------------- // Info about a read-only file inside a ZIP -class ZipFileInfo { +class ZipFileInfo final { public: explicit ZipFileInfo(unzFile zip_handle, size_t size); + ~ZipFileInfo() = default; // Allocate and Extract data from the ZIP ZipFile *Extract(std::string &filename, unzFile zip_handle) const; @@ -225,6 +237,7 @@ private: unz_file_pos_s m_ZipFilePos; }; +// ---------------------------------------------------------------- ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size) : m_Size(size) { ai_assert(m_Size != 0); @@ -234,6 +247,7 @@ ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size) : unzGetFilePos(zip_handle, &(m_ZipFilePos)); } +// ---------------------------------------------------------------- ZipFile *ZipFileInfo::Extract(std::string &filename, unzFile zip_handle) const { // Find in the ZIP. This cannot fail unz_file_pos_s *filepos = const_cast(&(m_ZipFilePos)); @@ -273,14 +287,14 @@ ZipFile *ZipFileInfo::Extract(std::string &filename, unzFile zip_handle) const { return zip_file; } +// ---------------------------------------------------------------- ZipFile::ZipFile(std::string &filename, size_t size) : m_Filename(filename), m_Size(size) { ai_assert(m_Size != 0); m_Buffer = std::unique_ptr(new uint8_t[m_Size]); } -ZipFile::~ZipFile() = default; - +// ---------------------------------------------------------------- size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) { // Should be impossible ai_assert(m_Buffer != nullptr); @@ -305,10 +319,12 @@ size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) { return pCount; } +// ---------------------------------------------------------------- size_t ZipFile::FileSize() const { return m_Size; } +// ---------------------------------------------------------------- aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) { switch (pOrigin) { case aiOrigin_SET: { @@ -334,6 +350,7 @@ aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) { return aiReturn_FAILURE; } +// ---------------------------------------------------------------- size_t ZipFile::Tell() const { return m_SeekPtr; } @@ -365,6 +382,7 @@ private: ZipFileInfoMap m_ArchiveMap; }; +// ---------------------------------------------------------------- ZipArchiveIOSystem::Implement::Implement(IOSystem *pIOHandler, const char *pFilename, const char *pMode) { ai_assert(strcmp(pMode, "r") == 0); ai_assert(pFilename != nullptr); @@ -376,12 +394,14 @@ ZipArchiveIOSystem::Implement::Implement(IOSystem *pIOHandler, const char *pFile m_ZipFileHandle = unzOpen2(pFilename, &mapping); } +// ---------------------------------------------------------------- ZipArchiveIOSystem::Implement::~Implement() { if (m_ZipFileHandle != nullptr) { unzClose(m_ZipFileHandle); } } +// ---------------------------------------------------------------- void ZipArchiveIOSystem::Implement::MapArchive() { if (m_ZipFileHandle == nullptr) return; @@ -408,10 +428,12 @@ void ZipArchiveIOSystem::Implement::MapArchive() { } while (unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE); } +// ---------------------------------------------------------------- bool ZipArchiveIOSystem::Implement::isOpen() const { return (m_ZipFileHandle != nullptr); } +// ---------------------------------------------------------------- void ZipArchiveIOSystem::Implement::getFileList(std::vector &rFileList) { MapArchive(); rFileList.clear(); @@ -421,6 +443,7 @@ void ZipArchiveIOSystem::Implement::getFileList(std::vector &rFileL } } +// ---------------------------------------------------------------- void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector &rFileList, const std::string &extension) { MapArchive(); rFileList.clear(); @@ -431,6 +454,7 @@ void ZipArchiveIOSystem::Implement::getFileListExtension(std::vectorExists(filename); } +// ---------------------------------------------------------------- // This is always '/' in a ZIP char ZipArchiveIOSystem::getOsSeparator() const { return '/'; } +// ---------------------------------------------------------------- // Only supports Reading IOStream *ZipArchiveIOSystem::Open(const char *pFilename, const char *pMode) { ai_assert(pFilename != nullptr); @@ -536,22 +569,27 @@ IOStream *ZipArchiveIOSystem::Open(const char *pFilename, const char *pMode) { return pImpl->OpenFile(filename); } +// ---------------------------------------------------------------- void ZipArchiveIOSystem::Close(IOStream *pFile) { delete pFile; } +// ---------------------------------------------------------------- bool ZipArchiveIOSystem::isOpen() const { return (pImpl->isOpen()); } +// ---------------------------------------------------------------- void ZipArchiveIOSystem::getFileList(std::vector &rFileList) const { return pImpl->getFileList(rFileList); } +// ---------------------------------------------------------------- void ZipArchiveIOSystem::getFileListExtension(std::vector &rFileList, const std::string &extension) const { return pImpl->getFileListExtension(rFileList, extension); } +// ---------------------------------------------------------------- bool ZipArchiveIOSystem::isZipArchive(IOSystem *pIOHandler, const char *pFilename) { Implement tmp(pIOHandler, pFilename, "r"); return tmp.isOpen(); diff --git a/code/Common/material.cpp b/code/Common/material.cpp index ffc2f415b..76676ec1a 100644 --- a/code/Common/material.cpp +++ b/code/Common/material.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/scene.cpp b/code/Common/scene.cpp index b0e882154..5c2e370d2 100644 --- a/code/Common/scene.cpp +++ b/code/Common/scene.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -40,6 +40,87 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include "ScenePrivate.h" + +aiScene::aiScene() : + mFlags(0), + mRootNode(nullptr), + mNumMeshes(0), + mMeshes(nullptr), + mNumMaterials(0), + mMaterials(nullptr), + mNumAnimations(0), + mAnimations(nullptr), + mNumTextures(0), + mTextures(nullptr), + mNumLights(0), + mLights(nullptr), + mNumCameras(0), + mCameras(nullptr), + mMetaData(nullptr), + mName(), + mNumSkeletons(0), + mSkeletons(nullptr), + mPrivate(new Assimp::ScenePrivateData()) { + // empty +} + +aiScene::~aiScene() { + // delete all sub-objects recursively + delete mRootNode; + + // To make sure we won't crash if the data is invalid it's + // much better to check whether both mNumXXX and mXXX are + // valid instead of relying on just one of them. + if (mNumMeshes && mMeshes) { + for (unsigned int a = 0; a < mNumMeshes; ++a) { + delete mMeshes[a]; + } + } + delete[] mMeshes; + + if (mNumMaterials && mMaterials) { + for (unsigned int a = 0; a < mNumMaterials; ++a) { + delete mMaterials[a]; + } + } + delete[] mMaterials; + + if (mNumAnimations && mAnimations) { + for (unsigned int a = 0; a < mNumAnimations; ++a) { + delete mAnimations[a]; + } + } + delete[] mAnimations; + + if (mNumTextures && mTextures) { + for (unsigned int a = 0; a < mNumTextures; ++a) { + delete mTextures[a]; + } + } + delete[] mTextures; + + if (mNumLights && mLights) { + for (unsigned int a = 0; a < mNumLights; ++a) { + delete mLights[a]; + } + } + delete[] mLights; + + if (mNumCameras && mCameras) { + for (unsigned int a = 0; a < mNumCameras; ++a) { + delete mCameras[a]; + } + } + delete[] mCameras; + + aiMetadata::Dealloc(mMetaData); + + delete[] mSkeletons; + + delete static_cast(mPrivate); +} + aiNode::aiNode() : mName(""), mParent(nullptr), diff --git a/code/Common/simd.cpp b/code/Common/simd.cpp index 0dd437d26..6a48750b0 100644 --- a/code/Common/simd.cpp +++ b/code/Common/simd.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Common/simd.h b/code/Common/simd.h index a1d936629..05d27d253 100644 --- a/code/Common/simd.h +++ b/code/Common/simd.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Geometry/GeometryUtils.cpp b/code/Geometry/GeometryUtils.cpp index cec1e74c5..375e501d3 100644 --- a/code/Geometry/GeometryUtils.cpp +++ b/code/Geometry/GeometryUtils.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Geometry/GeometryUtils.h b/code/Geometry/GeometryUtils.h index b6fff99e1..ae88d376b 100644 --- a/code/Geometry/GeometryUtils.h +++ b/code/Geometry/GeometryUtils.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -49,6 +49,10 @@ namespace Assimp { // --------------------------------------------------------------------------- class ASSIMP_API GeometryUtils { public: + /// @brief Will calculate the area of a triangle. + /// @param a The first vertex of the triangle. + /// @param b The first vertex of the triangle. + /// @param c The first vertex of the triangle. static ai_real heron( ai_real a, ai_real b, ai_real c ); /// @brief Will compute the distance between 2 3D-vectors diff --git a/code/Material/MaterialSystem.cpp b/code/Material/MaterialSystem.cpp index cc8ca2f88..7e2fb51b9 100644 --- a/code/Material/MaterialSystem.cpp +++ b/code/Material/MaterialSystem.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -486,7 +486,7 @@ aiReturn aiMaterial::AddBinaryProperty(const void *pInput, memcpy(pcNew->mData, pInput, pSizeInBytes); pcNew->mKey.length = static_cast(::strlen(pKey)); - ai_assert(MAXLEN > pcNew->mKey.length); + ai_assert(AI_MAXLEN > pcNew->mKey.length); strcpy(pcNew->mKey.data, pKey); if (UINT_MAX != iOutIndex) { diff --git a/code/Material/MaterialSystem.h b/code/Material/MaterialSystem.h index 41891ad97..e7c752179 100644 --- a/code/Material/MaterialSystem.h +++ b/code/Material/MaterialSystem.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Pbrt/PbrtExporter.cpp b/code/Pbrt/PbrtExporter.cpp index 9e4ca293d..907e9a6a2 100644 --- a/code/Pbrt/PbrtExporter.cpp +++ b/code/Pbrt/PbrtExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/Pbrt/PbrtExporter.h b/code/Pbrt/PbrtExporter.h index a4b1a608a..0242ddcf0 100644 --- a/code/Pbrt/PbrtExporter.h +++ b/code/Pbrt/PbrtExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 234a00232..fa524a7fd 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ArmaturePopulate.h b/code/PostProcessing/ArmaturePopulate.h index 52d3adfef..af1792fb0 100644 --- a/code/PostProcessing/ArmaturePopulate.h +++ b/code/PostProcessing/ArmaturePopulate.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/CalcTangentsProcess.cpp b/code/PostProcessing/CalcTangentsProcess.cpp index a23ac856b..abd0aee47 100644 --- a/code/PostProcessing/CalcTangentsProcess.cpp +++ b/code/PostProcessing/CalcTangentsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team @@ -185,9 +185,9 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) { tangent.x = (w.x * sy - v.x * ty) * dirCorrection; tangent.y = (w.y * sy - v.y * ty) * dirCorrection; tangent.z = (w.z * sy - v.z * ty) * dirCorrection; - bitangent.x = (- w.x * sx + v.x * tx) * dirCorrection; - bitangent.y = (- w.y * sx + v.y * tx) * dirCorrection; - bitangent.z = (- w.z * sx + v.z * tx) * dirCorrection; + bitangent.x = (w.x * sx - v.x * tx) * dirCorrection; + bitangent.y = (w.y * sx - v.y * tx) * dirCorrection; + bitangent.z = (w.z * sx - v.z * tx) * dirCorrection; // store for every vertex of that face for (unsigned int b = 0; b < face.mNumIndices; ++b) { @@ -195,7 +195,7 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) { // project tangent and bitangent into the plane formed by the vertex' normal aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]); - aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]) - localTangent * (bitangent * localTangent); + aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]); localTangent.NormalizeSafe(); localBitangent.NormalizeSafe(); diff --git a/code/PostProcessing/CalcTangentsProcess.h b/code/PostProcessing/CalcTangentsProcess.h index aaccb5307..3d7bb2a5e 100644 --- a/code/PostProcessing/CalcTangentsProcess.h +++ b/code/PostProcessing/CalcTangentsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ComputeUVMappingProcess.cpp b/code/PostProcessing/ComputeUVMappingProcess.cpp index f75dc5952..cac51e8d0 100644 --- a/code/PostProcessing/ComputeUVMappingProcess.cpp +++ b/code/PostProcessing/ComputeUVMappingProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -346,16 +346,20 @@ void ComputeUVMappingProcess::Execute(aiScene *pScene) { ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin"); char buffer[1024]; - if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) + if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here"); + } std::list mappingStack; - /* Iterate through all materials and search for non-UV mapped textures - */ + // Iterate through all materials and search for non-UV mapped textures for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { mappingStack.clear(); aiMaterial *mat = pScene->mMaterials[i]; + if (mat == nullptr) { + ASSIMP_LOG_INFO("Material pointer in nullptr, skipping."); + continue; + } for (unsigned int a = 0; a < mat->mNumProperties; ++a) { aiMaterialProperty *prop = mat->mProperties[a]; if (!::strcmp(prop->mKey.data, "$tex.mapping")) { diff --git a/code/PostProcessing/ComputeUVMappingProcess.h b/code/PostProcessing/ComputeUVMappingProcess.h index c4158f402..2a40a15b1 100644 --- a/code/PostProcessing/ComputeUVMappingProcess.h +++ b/code/PostProcessing/ComputeUVMappingProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ConvertToLHProcess.cpp b/code/PostProcessing/ConvertToLHProcess.cpp index 80abf84a5..77c7cb853 100644 --- a/code/PostProcessing/ConvertToLHProcess.cpp +++ b/code/PostProcessing/ConvertToLHProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ConvertToLHProcess.h b/code/PostProcessing/ConvertToLHProcess.h index ea001b95b..e5ef19a8d 100644 --- a/code/PostProcessing/ConvertToLHProcess.h +++ b/code/PostProcessing/ConvertToLHProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/DeboneProcess.cpp b/code/PostProcessing/DeboneProcess.cpp index e91196ce2..1ae79ee30 100644 --- a/code/PostProcessing/DeboneProcess.cpp +++ b/code/PostProcessing/DeboneProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/DeboneProcess.h b/code/PostProcessing/DeboneProcess.h index ae4448e0e..cc2d43cb7 100644 --- a/code/PostProcessing/DeboneProcess.h +++ b/code/PostProcessing/DeboneProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/DropFaceNormalsProcess.cpp b/code/PostProcessing/DropFaceNormalsProcess.cpp index c5f6333e0..29967b74b 100644 --- a/code/PostProcessing/DropFaceNormalsProcess.cpp +++ b/code/PostProcessing/DropFaceNormalsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/PostProcessing/DropFaceNormalsProcess.h b/code/PostProcessing/DropFaceNormalsProcess.h index df542f2ba..84f9dbe83 100644 --- a/code/PostProcessing/DropFaceNormalsProcess.h +++ b/code/PostProcessing/DropFaceNormalsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/EmbedTexturesProcess.cpp b/code/PostProcessing/EmbedTexturesProcess.cpp index d5d2ef872..568031d8f 100644 --- a/code/PostProcessing/EmbedTexturesProcess.cpp +++ b/code/PostProcessing/EmbedTexturesProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/EmbedTexturesProcess.h b/code/PostProcessing/EmbedTexturesProcess.h index 77d4d9c72..8210eec96 100644 --- a/code/PostProcessing/EmbedTexturesProcess.h +++ b/code/PostProcessing/EmbedTexturesProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/FindDegenerates.cpp b/code/PostProcessing/FindDegenerates.cpp index d9c14425c..c506b08b5 100644 --- a/code/PostProcessing/FindDegenerates.cpp +++ b/code/PostProcessing/FindDegenerates.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/FindDegenerates.h b/code/PostProcessing/FindDegenerates.h index 6b37a47cf..0d046df2d 100644 --- a/code/PostProcessing/FindDegenerates.h +++ b/code/PostProcessing/FindDegenerates.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/FindInstancesProcess.cpp b/code/PostProcessing/FindInstancesProcess.cpp index 55974b1c3..9186dd3dd 100644 --- a/code/PostProcessing/FindInstancesProcess.cpp +++ b/code/PostProcessing/FindInstancesProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/PostProcessing/FindInstancesProcess.h b/code/PostProcessing/FindInstancesProcess.h index 6927301ca..63e988abf 100644 --- a/code/PostProcessing/FindInstancesProcess.h +++ b/code/PostProcessing/FindInstancesProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/FindInvalidDataProcess.cpp b/code/PostProcessing/FindInvalidDataProcess.cpp index 64abf7589..12f345407 100644 --- a/code/PostProcessing/FindInvalidDataProcess.cpp +++ b/code/PostProcessing/FindInvalidDataProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/FindInvalidDataProcess.h b/code/PostProcessing/FindInvalidDataProcess.h index 024eb9b1e..516db4272 100644 --- a/code/PostProcessing/FindInvalidDataProcess.h +++ b/code/PostProcessing/FindInvalidDataProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/FixNormalsStep.cpp b/code/PostProcessing/FixNormalsStep.cpp index 54ac05cc8..2bf85430f 100644 --- a/code/PostProcessing/FixNormalsStep.cpp +++ b/code/PostProcessing/FixNormalsStep.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/PostProcessing/FixNormalsStep.h b/code/PostProcessing/FixNormalsStep.h index 20be1958b..b25d92282 100644 --- a/code/PostProcessing/FixNormalsStep.h +++ b/code/PostProcessing/FixNormalsStep.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/GenBoundingBoxesProcess.cpp b/code/PostProcessing/GenBoundingBoxesProcess.cpp index ca8e4d6d0..da9fd7137 100644 --- a/code/PostProcessing/GenBoundingBoxesProcess.cpp +++ b/code/PostProcessing/GenBoundingBoxesProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/GenBoundingBoxesProcess.h b/code/PostProcessing/GenBoundingBoxesProcess.h index 0cf8514f4..c24009dc9 100644 --- a/code/PostProcessing/GenBoundingBoxesProcess.h +++ b/code/PostProcessing/GenBoundingBoxesProcess.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/GenFaceNormalsProcess.cpp b/code/PostProcessing/GenFaceNormalsProcess.cpp index 1d259ce22..79a30ca24 100644 --- a/code/PostProcessing/GenFaceNormalsProcess.cpp +++ b/code/PostProcessing/GenFaceNormalsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/PostProcessing/GenFaceNormalsProcess.h b/code/PostProcessing/GenFaceNormalsProcess.h index 94794631e..a5aad13d1 100644 --- a/code/PostProcessing/GenFaceNormalsProcess.h +++ b/code/PostProcessing/GenFaceNormalsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/GenVertexNormalsProcess.cpp b/code/PostProcessing/GenVertexNormalsProcess.cpp index 4869263ab..f7fef6bc4 100644 --- a/code/PostProcessing/GenVertexNormalsProcess.cpp +++ b/code/PostProcessing/GenVertexNormalsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/GenVertexNormalsProcess.h b/code/PostProcessing/GenVertexNormalsProcess.h index b7db9c4f2..677c06a43 100644 --- a/code/PostProcessing/GenVertexNormalsProcess.h +++ b/code/PostProcessing/GenVertexNormalsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ImproveCacheLocality.cpp b/code/PostProcessing/ImproveCacheLocality.cpp index d7bb95698..c165b0114 100644 --- a/code/PostProcessing/ImproveCacheLocality.cpp +++ b/code/PostProcessing/ImproveCacheLocality.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ImproveCacheLocality.h b/code/PostProcessing/ImproveCacheLocality.h index 6f4d55719..30fa59608 100644 --- a/code/PostProcessing/ImproveCacheLocality.h +++ b/code/PostProcessing/ImproveCacheLocality.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/JoinVerticesProcess.cpp b/code/PostProcessing/JoinVerticesProcess.cpp index 4de6c3e1b..f4c623c98 100644 --- a/code/PostProcessing/JoinVerticesProcess.cpp +++ b/code/PostProcessing/JoinVerticesProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/JoinVerticesProcess.h b/code/PostProcessing/JoinVerticesProcess.h index aa8dc5794..60630dae3 100644 --- a/code/PostProcessing/JoinVerticesProcess.h +++ b/code/PostProcessing/JoinVerticesProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/LimitBoneWeightsProcess.cpp b/code/PostProcessing/LimitBoneWeightsProcess.cpp index 16b32143e..816914ada 100644 --- a/code/PostProcessing/LimitBoneWeightsProcess.cpp +++ b/code/PostProcessing/LimitBoneWeightsProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2023, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/LimitBoneWeightsProcess.h b/code/PostProcessing/LimitBoneWeightsProcess.h index 8e5ebd80d..b2612c313 100644 --- a/code/PostProcessing/LimitBoneWeightsProcess.h +++ b/code/PostProcessing/LimitBoneWeightsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/MakeVerboseFormat.cpp b/code/PostProcessing/MakeVerboseFormat.cpp index 1cc2fdc02..d0c5693e7 100644 --- a/code/PostProcessing/MakeVerboseFormat.cpp +++ b/code/PostProcessing/MakeVerboseFormat.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/PostProcessing/MakeVerboseFormat.h b/code/PostProcessing/MakeVerboseFormat.h index f21f5919e..02fe21fa7 100644 --- a/code/PostProcessing/MakeVerboseFormat.h +++ b/code/PostProcessing/MakeVerboseFormat.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/OptimizeGraph.cpp b/code/PostProcessing/OptimizeGraph.cpp index bcd654634..01f6fca14 100644 --- a/code/PostProcessing/OptimizeGraph.cpp +++ b/code/PostProcessing/OptimizeGraph.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -164,7 +164,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n ++it; } if (join_master && !join.empty()) { - join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%u", count_merged++); + join_master->mName.length = ::ai_snprintf(join_master->mName.data, AI_MAXLEN, "$MergedNode_%u", count_merged++); unsigned int out_meshes = 0; for (std::list::const_iterator it = join.cbegin(); it != join.cend(); ++it) { diff --git a/code/PostProcessing/OptimizeGraph.h b/code/PostProcessing/OptimizeGraph.h index 23e59e67d..c32748d7f 100644 --- a/code/PostProcessing/OptimizeGraph.h +++ b/code/PostProcessing/OptimizeGraph.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/OptimizeMeshes.cpp b/code/PostProcessing/OptimizeMeshes.cpp index 0fd597808..44792420c 100644 --- a/code/PostProcessing/OptimizeMeshes.cpp +++ b/code/PostProcessing/OptimizeMeshes.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team diff --git a/code/PostProcessing/OptimizeMeshes.h b/code/PostProcessing/OptimizeMeshes.h index 0b062959a..e424ae24a 100644 --- a/code/PostProcessing/OptimizeMeshes.h +++ b/code/PostProcessing/OptimizeMeshes.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index aff6e535a..0203ac211 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -635,7 +635,7 @@ void PretransformVertices::Execute(aiScene *pScene) { aiNode *pcNode = new aiNode(); *nodes = pcNode; pcNode->mParent = pScene->mRootNode; - pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "light_%u", i); + pcNode->mName.length = ai_snprintf(pcNode->mName.data, AI_MAXLEN, "light_%u", i); pScene->mLights[i]->mName = pcNode->mName; } // generate camera nodes @@ -643,7 +643,7 @@ void PretransformVertices::Execute(aiScene *pScene) { aiNode *pcNode = new aiNode(); *nodes = pcNode; pcNode->mParent = pScene->mRootNode; - pcNode->mName.length = ::ai_snprintf(pcNode->mName.data, MAXLEN, "cam_%u", i); + pcNode->mName.length = ::ai_snprintf(pcNode->mName.data, AI_MAXLEN, "cam_%u", i); pScene->mCameras[i]->mName = pcNode->mName; } } diff --git a/code/PostProcessing/PretransformVertices.h b/code/PostProcessing/PretransformVertices.h index 69d3d8400..74c886488 100644 --- a/code/PostProcessing/PretransformVertices.h +++ b/code/PostProcessing/PretransformVertices.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ProcessHelper.cpp b/code/PostProcessing/ProcessHelper.cpp index e55c17648..cfbac3e80 100644 --- a/code/PostProcessing/ProcessHelper.cpp +++ b/code/PostProcessing/ProcessHelper.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -52,8 +52,9 @@ namespace Assimp { // ------------------------------------------------------------------------------- void ConvertListToStrings(const std::string &in, std::list &out) { const char *s = in.c_str(); + const char *end = in.c_str() + in.size(); while (*s) { - SkipSpacesAndLineEnd(&s); + SkipSpacesAndLineEnd(&s, end); if (*s == '\'') { const char *base = ++s; while (*s != '\'') { @@ -66,7 +67,7 @@ void ConvertListToStrings(const std::string &in, std::list &out) { out.emplace_back(base, (size_t)(s - base)); ++s; } else { - out.push_back(GetNextToken(s)); + out.push_back(GetNextToken(s, end)); } } } @@ -176,8 +177,8 @@ unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh) { if (pcMesh->HasTangentsAndBitangents()) iRet |= 0x4; - static_assert(8 >= AI_MAX_NUMBER_OF_COLOR_SETS); - static_assert(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS); + static_assert(8 >= AI_MAX_NUMBER_OF_COLOR_SETS, "static_assert(8 >= AI_MAX_NUMBER_OF_COLOR_SETS)"); + static_assert(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS, "static_assert(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS)"); // texture coordinates unsigned int p = 0; diff --git a/code/PostProcessing/ProcessHelper.h b/code/PostProcessing/ProcessHelper.h index 78df94ca1..273b122ae 100644 --- a/code/PostProcessing/ProcessHelper.h +++ b/code/PostProcessing/ProcessHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/RemoveRedundantMaterials.cpp b/code/PostProcessing/RemoveRedundantMaterials.cpp index ea8d154dc..111c233b1 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.cpp +++ b/code/PostProcessing/RemoveRedundantMaterials.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -75,124 +75,129 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess begin"); unsigned int redundantRemoved = 0, unreferencedRemoved = 0; - if (pScene->mNumMaterials) { - // Find out which materials are referenced by meshes - std::vector abReferenced(pScene->mNumMaterials,false); - for (unsigned int i = 0;i < pScene->mNumMeshes;++i) - abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true; + if (pScene->mNumMaterials == 0) { + return; + } + + // Find out which materials are referenced by meshes + std::vector abReferenced(pScene->mNumMaterials,false); + for (unsigned int i = 0;i < pScene->mNumMeshes;++i) { + abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true; + } - // If a list of materials to be excluded was given, match the list with - // our imported materials and 'salt' all positive matches to ensure that - // we get unique hashes later. - if (mConfigFixedMaterials.length()) { + // If a list of materials to be excluded was given, match the list with + // our imported materials and 'salt' all positive matches to ensure that + // we get unique hashes later. + if (mConfigFixedMaterials.length()) { + std::list strings; + ConvertListToStrings(mConfigFixedMaterials,strings); - std::list strings; - ConvertListToStrings(mConfigFixedMaterials,strings); + for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { + aiMaterial* mat = pScene->mMaterials[i]; + ai_assert(mat != nullptr); + aiString name; + mat->Get(AI_MATKEY_NAME,name); - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { - aiMaterial* mat = pScene->mMaterials[i]; + if (name.length != 0) { + std::list::const_iterator it = std::find(strings.begin(), strings.end(), name.data); + if (it != strings.end()) { + // Our brilliant 'salt': A single material property with ~ as first + // character to mark it as internal and temporary. + const int dummy = 1; + ((aiMaterial*)mat)->AddProperty(&dummy,1,"~RRM.UniqueMaterial",0,0); - aiString name; - mat->Get(AI_MATKEY_NAME,name); - - if (name.length) { - std::list::const_iterator it = std::find(strings.begin(), strings.end(), name.data); - if (it != strings.end()) { - - // Our brilliant 'salt': A single material property with ~ as first - // character to mark it as internal and temporary. - const int dummy = 1; - ((aiMaterial*)mat)->AddProperty(&dummy,1,"~RRM.UniqueMaterial",0,0); - - // Keep this material even if no mesh references it - abReferenced[i] = true; - ASSIMP_LOG_VERBOSE_DEBUG( "Found positive match in exclusion list: \'", name.data, "\'"); - } + // Keep this material even if no mesh references it + abReferenced[i] = true; + ASSIMP_LOG_VERBOSE_DEBUG( "Found positive match in exclusion list: \'", name.data, "\'"); } } } + } - // TODO: re-implement this algorithm to work in-place - unsigned int *aiMappingTable = new unsigned int[pScene->mNumMaterials]; - for ( unsigned int i=0; imNumMaterials; i++ ) { - aiMappingTable[ i ] = 0; + // TODO: re-implement this algorithm to work in-place + unsigned int *aiMappingTable = new unsigned int[pScene->mNumMaterials]; + for ( unsigned int i=0; imNumMaterials; i++ ) { + aiMappingTable[ i ] = 0; + } + unsigned int iNewNum = 0; + + // Iterate through all materials and calculate a hash for them + // store all hashes in a list and so a quick search whether + // we do already have a specific hash. This allows us to + // determine which materials are identical. + uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ]; + for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { + // No mesh is referencing this material, remove it. + if (!abReferenced[i]) { + ++unreferencedRemoved; + delete pScene->mMaterials[i]; + pScene->mMaterials[i] = nullptr; + continue; } - unsigned int iNewNum = 0; - // Iterate through all materials and calculate a hash for them - // store all hashes in a list and so a quick search whether - // we do already have a specific hash. This allows us to - // determine which materials are identical. - uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { - // No mesh is referencing this material, remove it. - if (!abReferenced[i]) { - ++unreferencedRemoved; + // Check all previously mapped materials for a matching hash. + // On a match we can delete this material and just make it ref to the same index. + uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]); + for (unsigned int a = 0; a < i;++a) { + if (abReferenced[a] && me == aiHashes[a]) { + ++redundantRemoved; + me = 0; + aiMappingTable[i] = aiMappingTable[a]; delete pScene->mMaterials[i]; pScene->mMaterials[i] = nullptr; + break; + } + } + // This is a new material that is referenced, add to the map. + if (me) { + aiMappingTable[i] = iNewNum++; + } + } + // If the new material count differs from the original, + // we need to rebuild the material list and remap mesh material indexes. + if (iNewNum < 1) { + delete [] aiMappingTable; + delete [] aiHashes; + pScene->mNumMaterials = 0; + return; + } + if (iNewNum != pScene->mNumMaterials) { + ai_assert(iNewNum > 0); + aiMaterial** ppcMaterials = new aiMaterial*[iNewNum]; + ::memset(ppcMaterials,0,sizeof(void*)*iNewNum); + for (unsigned int p = 0; p < pScene->mNumMaterials;++p) { + // if the material is not referenced ... remove it + if (!abReferenced[p]) { continue; } - // Check all previously mapped materials for a matching hash. - // On a match we can delete this material and just make it ref to the same index. - uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]); - for (unsigned int a = 0; a < i;++a) { - if (abReferenced[a] && me == aiHashes[a]) { - ++redundantRemoved; - me = 0; - aiMappingTable[i] = aiMappingTable[a]; - delete pScene->mMaterials[i]; - pScene->mMaterials[i] = nullptr; - break; + // generate new names for modified materials that had no names + const unsigned int idx = aiMappingTable[p]; + if (ppcMaterials[idx]) { + aiString sz; + if( ppcMaterials[idx]->Get(AI_MATKEY_NAME, sz) != AI_SUCCESS ) { + sz.length = ::ai_snprintf(sz.data, AI_MAXLEN,"JoinedMaterial_#%u",p); + ((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME); } - } - // This is a new material that is referenced, add to the map. - if (me) { - aiMappingTable[i] = iNewNum++; + } else { + ppcMaterials[idx] = pScene->mMaterials[p]; } } - // If the new material count differs from the original, - // we need to rebuild the material list and remap mesh material indexes. - if(iNewNum < 1) - throw DeadlyImportError("No materials remaining"); - if (iNewNum != pScene->mNumMaterials) { - ai_assert(iNewNum > 0); - aiMaterial** ppcMaterials = new aiMaterial*[iNewNum]; - ::memset(ppcMaterials,0,sizeof(void*)*iNewNum); - for (unsigned int p = 0; p < pScene->mNumMaterials;++p) - { - // if the material is not referenced ... remove it - if (!abReferenced[p]) { - continue; - } - - // generate new names for modified materials that had no names - const unsigned int idx = aiMappingTable[p]; - if (ppcMaterials[idx]) { - aiString sz; - if( ppcMaterials[idx]->Get(AI_MATKEY_NAME, sz) != AI_SUCCESS ) { - sz.length = ::ai_snprintf(sz.data,MAXLEN,"JoinedMaterial_#%u",p); - ((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME); - } - } else { - ppcMaterials[idx] = pScene->mMaterials[p]; - } - } - // update all material indices - for (unsigned int p = 0; p < pScene->mNumMeshes;++p) { - aiMesh* mesh = pScene->mMeshes[p]; - ai_assert(nullptr != mesh); - mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex]; - } - // delete the old material list - delete[] pScene->mMaterials; - pScene->mMaterials = ppcMaterials; - pScene->mNumMaterials = iNewNum; + // update all material indices + for (unsigned int p = 0; p < pScene->mNumMeshes;++p) { + aiMesh* mesh = pScene->mMeshes[p]; + ai_assert(nullptr != mesh); + mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex]; } - // delete temporary storage - delete[] aiHashes; - delete[] aiMappingTable; + // delete the old material list + delete[] pScene->mMaterials; + pScene->mMaterials = ppcMaterials; + pScene->mNumMaterials = iNewNum; } + // delete temporary storage + delete[] aiHashes; + delete[] aiMappingTable; + if (redundantRemoved == 0 && unreferencedRemoved == 0) { ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess finished "); } else { diff --git a/code/PostProcessing/RemoveRedundantMaterials.h b/code/PostProcessing/RemoveRedundantMaterials.h index 1b42bea55..107de0daa 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.h +++ b/code/PostProcessing/RemoveRedundantMaterials.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/RemoveVCProcess.cpp b/code/PostProcessing/RemoveVCProcess.cpp index bcad65423..13ef81e23 100644 --- a/code/PostProcessing/RemoveVCProcess.cpp +++ b/code/PostProcessing/RemoveVCProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/RemoveVCProcess.h b/code/PostProcessing/RemoveVCProcess.h index 45c0b3a71..8d9b5167a 100644 --- a/code/PostProcessing/RemoveVCProcess.h +++ b/code/PostProcessing/RemoveVCProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ScaleProcess.cpp b/code/PostProcessing/ScaleProcess.cpp index 1bb9196f1..5cd7eea6e 100644 --- a/code/PostProcessing/ScaleProcess.cpp +++ b/code/PostProcessing/ScaleProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ScaleProcess.h b/code/PostProcessing/ScaleProcess.h index ae1c3ed00..2887c7221 100644 --- a/code/PostProcessing/ScaleProcess.h +++ b/code/PostProcessing/ScaleProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index 47633dce5..48ebbc573 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/SortByPTypeProcess.h b/code/PostProcessing/SortByPTypeProcess.h index ce4f7da62..aa7774d7f 100644 --- a/code/PostProcessing/SortByPTypeProcess.h +++ b/code/PostProcessing/SortByPTypeProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index 969146fee..f63478767 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -394,7 +394,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumMeshes == 0 ) { + if( pNode->mNumMeshes != 0 ) { IndexArray newMeshList; for( unsigned int a = 0; a < pNode->mNumMeshes; ++a) { unsigned int srcIndex = pNode->mMeshes[a]; diff --git a/code/PostProcessing/SplitByBoneCountProcess.h b/code/PostProcessing/SplitByBoneCountProcess.h index efe85824f..c90661cb5 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.h +++ b/code/PostProcessing/SplitByBoneCountProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/SplitLargeMeshes.cpp b/code/PostProcessing/SplitLargeMeshes.cpp index b6e5b772a..3bee28521 100644 --- a/code/PostProcessing/SplitLargeMeshes.cpp +++ b/code/PostProcessing/SplitLargeMeshes.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/SplitLargeMeshes.h b/code/PostProcessing/SplitLargeMeshes.h index 4e0d764c1..25bf300d5 100644 --- a/code/PostProcessing/SplitLargeMeshes.h +++ b/code/PostProcessing/SplitLargeMeshes.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index 3de357c17..228e97e42 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -390,8 +390,8 @@ void TextureTransformStep::Execute( aiScene* pScene) { cnt = 0; for (it = trafo.begin();it != trafo.end(); ++it,++cnt) { if ((*it).lockedPos != AI_TT_UV_IDX_LOCK_NONE && (*it).lockedPos != cnt) { - it2 = trafo.begin();unsigned int t = 0; - while (t != (*it).lockedPos) + it2 = trafo.begin(); + while ((*it2).lockedPos != (*it).lockedPos) ++it2; if ((*it2).lockedPos != AI_TT_UV_IDX_LOCK_NONE) { diff --git a/code/PostProcessing/TextureTransform.h b/code/PostProcessing/TextureTransform.h index c9f0480ba..7c0addf09 100644 --- a/code/PostProcessing/TextureTransform.h +++ b/code/PostProcessing/TextureTransform.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index f16de2196..ac483f215 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/TriangulateProcess.h b/code/PostProcessing/TriangulateProcess.h index ac31e4377..e17a10e33 100644 --- a/code/PostProcessing/TriangulateProcess.h +++ b/code/PostProcessing/TriangulateProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index 14259e11a..1dd5d436a 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. @@ -909,9 +909,9 @@ void ValidateDSProcess::Validate(const aiNode *pNode) { // ------------------------------------------------------------------------------------------------ void ValidateDSProcess::Validate(const aiString *pString) { - if (pString->length > MAXLEN) { + if (pString->length > AI_MAXLEN) { ReportError("aiString::length is too large (%u, maximum is %lu)", - pString->length, MAXLEN); + pString->length, AI_MAXLEN); } const char *sz = pString->data; while (true) { @@ -920,7 +920,7 @@ void ValidateDSProcess::Validate(const aiString *pString) { ReportError("aiString::data is invalid: the terminal zero is at a wrong offset"); } break; - } else if (sz >= &pString->data[MAXLEN]) { + } else if (sz >= &pString->data[AI_MAXLEN]) { ReportError("aiString::data is invalid. There is no terminal character"); } ++sz; diff --git a/code/PostProcessing/ValidateDataStructure.h b/code/PostProcessing/ValidateDataStructure.h index 9cfd4ced1..8bc13e60d 100644 --- a/code/PostProcessing/ValidateDataStructure.h +++ b/code/PostProcessing/ValidateDataStructure.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2024, assimp team All rights reserved. diff --git a/code/res/assimp.rc b/code/res/assimp.rc index fd10935f6..6c9356276 100644 --- a/code/res/assimp.rc +++ b/code/res/assimp.rc @@ -1,4 +1,4 @@ -#include "revision.h" +#include #ifdef __GNUC__ #include "winresrc.h" #else diff --git a/contrib/clipper/clipper.cpp b/contrib/clipper/clipper.cpp index d75974336..c0a8565bb 100644 --- a/contrib/clipper/clipper.cpp +++ b/contrib/clipper/clipper.cpp @@ -4330,10 +4330,10 @@ double DistanceFromLineSqrd( const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) { //The equation of a line in general form (Ax + By + C = 0) - //given 2 points (x�,y�) & (x�,y�) is ... - //(y� - y�)x + (x� - x�)y + (y� - y�)x� - (x� - x�)y� = 0 - //A = (y� - y�); B = (x� - x�); C = (y� - y�)x� - (x� - x�)y� - //perpendicular distance of point (x�,y�) = (Ax� + By� + C)/Sqrt(A� + B�) + //given 2 points (x_1, y_1) & (x_2, y_2) is ... + //(y_1 - y_2)x + (x_2 - x_1)y - (y_1 - y_2)x_1 - (x_2 - x_1)y_1 = 0 + //A = (y_1 - y_2); B = (x_2 - x_1); C = - (y_1 - y_2)x_1 - (x_2 - x_1)y_1 + //perpendicular distance of point (x_0, y_0) = |Ax_0 + By_0 + C| / Sqrt(A^2 + B^2) //see http://en.wikipedia.org/wiki/Perpendicular_distance double A = double(ln1.Y - ln2.Y); double B = double(ln2.X - ln1.X); diff --git a/contrib/draco/BUILDING.md b/contrib/draco/BUILDING.md index 340b2b83b..8e1f13e1f 100644 --- a/contrib/draco/BUILDING.md +++ b/contrib/draco/BUILDING.md @@ -1,21 +1,23 @@ _**Contents**_ - * [CMake Basics](#cmake-basics) - * [Mac OS X](#mac-os-x) - * [Windows](#windows) - * [CMake Build Configuration](#cmake-build-configuration) - * [Transcoder](#transcoder) - * [Debugging and Optimization](#debugging-and-optimization) - * [Googletest Integration](#googletest-integration) - * [Third Party Libraries](#third-party-libraries) - * [Javascript Encoder/Decoder](#javascript-encoderdecoder) - * [WebAssembly Decoder](#webassembly-decoder) - * [WebAssembly Mesh Only Decoder](#webassembly-mesh-only-decoder) - * [WebAssembly Point Cloud Only Decoder](#webassembly-point-cloud-only-decoder) - * [iOS Builds](#ios-builds) - * [Android Studio Project Integration](#android-studio-project-integration) - * [Native Android Builds](#native-android-builds) - * [vcpkg](#vcpkg) +- [Building](#building) + - [CMake Basics](#cmake-basics) + - [Mac OS X](#mac-os-x) + - [Windows](#windows) + - [CMake Build Configuration](#cmake-build-configuration) + - [Transcoder](#transcoder) + - [Debugging and Optimization](#debugging-and-optimization) + - [Googletest Integration](#googletest-integration) + - [Third Party Libraries](#third-party-libraries) + - [WebAssembly Decoder](#webassembly-decoder) + - [WebAssembly Mesh Only Decoder](#webassembly-mesh-only-decoder) + - [WebAssembly Point Cloud Only Decoder](#webassembly-point-cloud-only-decoder) + - [Javascript Encoder/Decoder](#javascript-encoderdecoder) + - [iOS Builds](#ios-builds) + - [Native Android Builds](#native-android-builds) + - [Android Studio Project Integration](#android-studio-project-integration) + - [Draco - Static Library](#draco---static-library) + - [vcpkg](#vcpkg) Building ======== @@ -325,7 +327,7 @@ Draco - Static Library To include Draco in an existing or new Android Studio project, reference it from the `cmake` file of an existing native project that has a minimum SDK -version of 18 or higher. The project must support C++11. +version of 18 or higher. The project must support C++11 at least. To add Draco to your project: 1. Create a new "Native C++" project. diff --git a/contrib/pugixml/readme.txt b/contrib/pugixml/readme.txt index 9dffb72a1..2c1865437 100644 --- a/contrib/pugixml/readme.txt +++ b/contrib/pugixml/readme.txt @@ -1,6 +1,6 @@ pugixml 1.13 - an XML processing library -Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) +Copyright (c) 2006-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) Report bugs and download new versions at https://pugixml.org/ This is the distribution of pugixml, which is a C++ XML processing library, @@ -26,7 +26,7 @@ The distribution contains the following folders: This library is distributed under the MIT License: -Copyright (c) 2006-2022 Arseny Kapoulkine +Copyright (c) 2006-2024 Arseny Kapoulkine Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/contrib/pugixml/src/pugiconfig.hpp b/contrib/pugixml/src/pugiconfig.hpp index 9bf2efd39..1a3956903 100644 --- a/contrib/pugixml/src/pugiconfig.hpp +++ b/contrib/pugixml/src/pugiconfig.hpp @@ -1,7 +1,7 @@ /** * pugixml parser - version 1.13 * -------------------------------------------------------- - * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (c) 2006-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -52,7 +52,7 @@ #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2024 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/contrib/pugixml/src/pugixml.cpp b/contrib/pugixml/src/pugixml.cpp index c63645b67..6d6bd0edb 100644 --- a/contrib/pugixml/src/pugixml.cpp +++ b/contrib/pugixml/src/pugixml.cpp @@ -1,7 +1,7 @@ /** * pugixml parser - version 1.13 * -------------------------------------------------------- - * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (c) 2006-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -13133,7 +13133,7 @@ namespace pugi #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2024 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/contrib/pugixml/src/pugixml.hpp b/contrib/pugixml/src/pugixml.hpp index 050df154c..fde6a4a86 100644 --- a/contrib/pugixml/src/pugixml.hpp +++ b/contrib/pugixml/src/pugixml.hpp @@ -1,7 +1,7 @@ /** * pugixml parser - version 1.13 * -------------------------------------------------------- - * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (c) 2006-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -1481,7 +1481,7 @@ namespace std #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2024 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/contrib/rapidjson/include/rapidjson/allocators.h b/contrib/rapidjson/include/rapidjson/allocators.h index 44ec5295c..275417bd8 100644 --- a/contrib/rapidjson/include/rapidjson/allocators.h +++ b/contrib/rapidjson/include/rapidjson/allocators.h @@ -16,6 +16,14 @@ #define RAPIDJSON_ALLOCATORS_H_ #include "rapidjson.h" +#include "internal/meta.h" + +#include +#include + +#if RAPIDJSON_HAS_CXX11 +#include +#endif RAPIDJSON_NAMESPACE_BEGIN @@ -89,7 +97,14 @@ public: } return RAPIDJSON_REALLOC(originalPtr, newSize); } - static void Free(void *ptr) { RAPIDJSON_FREE(ptr); } + static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); } + + bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { + return true; + } + bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { + return false; + } }; /////////////////////////////////////////////////////////////////////////////// @@ -113,16 +128,64 @@ public: */ template class MemoryPoolAllocator { + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + struct SharedData { + ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + BaseAllocator* ownBaseAllocator; //!< base allocator created by this object. + size_t refcount; + bool ownBuffer; + }; + + static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData)); + static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader)); + + static inline ChunkHeader *GetChunkHead(SharedData *shared) + { + return reinterpret_cast(reinterpret_cast(shared) + SIZEOF_SHARED_DATA); + } + static inline uint8_t *GetChunkBuffer(SharedData *shared) + { + return reinterpret_cast(shared->chunkHead) + SIZEOF_CHUNK_HEADER; + } + + static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity. + public: static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy //! Constructor with chunkSize. /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. \param baseAllocator The allocator for allocating memory chunks. */ + explicit MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : - chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + chunk_capacity_(chunkSize), + baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()), + shared_(static_cast(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0)) { + RAPIDJSON_ASSERT(baseAllocator_ != 0); + RAPIDJSON_ASSERT(shared_ != 0); + if (baseAllocator) { + shared_->ownBaseAllocator = 0; + } + else { + shared_->ownBaseAllocator = baseAllocator_; + } + shared_->chunkHead = GetChunkHead(shared_); + shared_->chunkHead->capacity = 0; + shared_->chunkHead->size = 0; + shared_->chunkHead->next = 0; + shared_->ownBuffer = true; + shared_->refcount = 1; } //! Constructor with user-supplied buffer. @@ -136,41 +199,101 @@ public: \param baseAllocator The allocator for allocating memory chunks. */ MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : - chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + chunk_capacity_(chunkSize), + baseAllocator_(baseAllocator), + shared_(static_cast(AlignBuffer(buffer, size))) { - RAPIDJSON_ASSERT(buffer != 0); - RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); - chunkHead_ = reinterpret_cast(buffer); - chunkHead_->capacity = size - sizeof(ChunkHeader); - chunkHead_->size = 0; - chunkHead_->next = 0; + RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER); + shared_->chunkHead = GetChunkHead(shared_); + shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER; + shared_->chunkHead->size = 0; + shared_->chunkHead->next = 0; + shared_->ownBaseAllocator = 0; + shared_->ownBuffer = false; + shared_->refcount = 1; } + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(rhs.baseAllocator_), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + ++shared_->refcount; + } + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + ++rhs.shared_->refcount; + this->~MemoryPoolAllocator(); + baseAllocator_ = rhs.baseAllocator_; + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(rhs.baseAllocator_), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + rhs.shared_ = 0; + } + MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + this->~MemoryPoolAllocator(); + baseAllocator_ = rhs.baseAllocator_; + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + rhs.shared_ = 0; + return *this; + } +#endif + //! Destructor. /*! This deallocates all memory chunks, excluding the user-supplied buffer. */ - ~MemoryPoolAllocator() { + ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT { + if (!shared_) { + // do nothing if moved + return; + } + if (shared_->refcount > 1) { + --shared_->refcount; + return; + } Clear(); - RAPIDJSON_DELETE(ownBaseAllocator_); + BaseAllocator *a = shared_->ownBaseAllocator; + if (shared_->ownBuffer) { + baseAllocator_->Free(shared_); + } + RAPIDJSON_DELETE(a); } - //! Deallocates all memory chunks, excluding the user-supplied buffer. - void Clear() { - while (chunkHead_ && chunkHead_ != userBuffer_) { - ChunkHeader* next = chunkHead_->next; - baseAllocator_->Free(chunkHead_); - chunkHead_ = next; + //! Deallocates all memory chunks, excluding the first/user one. + void Clear() RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + for (;;) { + ChunkHeader* c = shared_->chunkHead; + if (!c->next) { + break; + } + shared_->chunkHead = c->next; + baseAllocator_->Free(c); } - if (chunkHead_ && chunkHead_ == userBuffer_) - chunkHead_->size = 0; // Clear user buffer + shared_->chunkHead->size = 0; } //! Computes the total capacity of allocated memory chunks. /*! \return total capacity in bytes. */ - size_t Capacity() const { + size_t Capacity() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); size_t capacity = 0; - for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) capacity += c->capacity; return capacity; } @@ -178,25 +301,35 @@ public: //! Computes the memory blocks allocated. /*! \return total used bytes. */ - size_t Size() const { + size_t Size() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); size_t size = 0; - for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) size += c->size; return size; } + //! Whether the allocator is shared. + /*! \return true or false. + */ + bool Shared() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + return shared_->refcount > 1; + } + //! Allocates a memory block. (concept Allocator) void* Malloc(size_t size) { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); if (!size) return NULL; size = RAPIDJSON_ALIGN(size); - if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) + if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity)) if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) return NULL; - void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; - chunkHead_->size += size; + void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size; + shared_->chunkHead->size += size; return buffer; } @@ -205,6 +338,7 @@ public: if (originalPtr == 0) return Malloc(newSize); + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); if (newSize == 0) return NULL; @@ -216,10 +350,10 @@ public: return originalPtr; // Simply expand it if it is the last allocation and there is sufficient space - if (originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { + if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) { size_t increment = static_cast(newSize - originalSize); - if (chunkHead_->size + increment <= chunkHead_->capacity) { - chunkHead_->size += increment; + if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) { + shared_->chunkHead->size += increment; return originalPtr; } } @@ -235,50 +369,325 @@ public: } //! Frees a memory block (concept Allocator) - static void Free(void *ptr) { (void)ptr; } // Do nothing + static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing + + //! Compare (equality) with another MemoryPoolAllocator + bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + return shared_ == rhs.shared_; + } + //! Compare (inequality) with another MemoryPoolAllocator + bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { + return !operator==(rhs); + } private: - //! Copy constructor is not permitted. - MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; - //! Copy assignment operator is not permitted. - MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; - //! Creates a new chunk. /*! \param capacity Capacity of the chunk in bytes. \return true if success. */ bool AddChunk(size_t capacity) { if (!baseAllocator_) - ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); - if (ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { + shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); + if (ChunkHeader* chunk = static_cast(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) { chunk->capacity = capacity; chunk->size = 0; - chunk->next = chunkHead_; - chunkHead_ = chunk; + chunk->next = shared_->chunkHead; + shared_->chunkHead = chunk; return true; } else return false; } - static const int kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity. + static inline void* AlignBuffer(void* buf, size_t &size) + { + RAPIDJSON_NOEXCEPT_ASSERT(buf != 0); + const uintptr_t mask = sizeof(void*) - 1; + const uintptr_t ubuf = reinterpret_cast(buf); + if (RAPIDJSON_UNLIKELY(ubuf & mask)) { + const uintptr_t abuf = (ubuf + mask) & ~mask; + RAPIDJSON_ASSERT(size >= abuf - ubuf); + buf = reinterpret_cast(abuf); + size -= abuf - ubuf; + } + return buf; + } - //! Chunk header for perpending to each chunk. - /*! Chunks are stored as a singly linked list. - */ - struct ChunkHeader { - size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). - size_t size; //!< Current size of allocated memory in bytes. - ChunkHeader *next; //!< Next chunk in the linked list. + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + SharedData *shared_; //!< The shared data of the allocator +}; + +namespace internal { + template + struct IsRefCounted : + public FalseType + { }; + template + struct IsRefCounted::Type> : + public TrueType + { }; +} + +template +inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) +{ + RAPIDJSON_NOEXCEPT_ASSERT(old_n <= (std::numeric_limits::max)() / sizeof(T) && new_n <= (std::numeric_limits::max)() / sizeof(T)); + return static_cast(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); +} + +template +inline T *Malloc(A& a, size_t n = 1) +{ + return Realloc(a, NULL, 0, n); +} + +template +inline void Free(A& a, T *p, size_t n = 1) +{ + static_cast(Realloc(a, p, n, 0)); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited +#endif + +template +class StdAllocator : + public std::allocator +{ + typedef std::allocator allocator_type; +#if RAPIDJSON_HAS_CXX11 + typedef std::allocator_traits traits_type; +#else + typedef allocator_type traits_type; +#endif + +public: + typedef BaseAllocator BaseAllocatorType; + + StdAllocator() RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_() + { } + + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + template + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(std::move(rhs)), + baseAllocator_(std::move(rhs.baseAllocator_)) + { } +#endif +#if RAPIDJSON_HAS_CXX11 + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; +#endif + + /* implicit */ + StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(baseAllocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template + struct rebind { + typedef StdAllocator other; }; - ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. - size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. - void *userBuffer_; //!< User supplied buffer. - BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. - BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. + typedef typename traits_type::size_type size_type; + typedef typename traits_type::difference_type difference_type; + + typedef typename traits_type::value_type value_type; + typedef typename traits_type::pointer pointer; + typedef typename traits_type::const_pointer const_pointer; + +#if RAPIDJSON_HAS_CXX11 + + typedef typename std::add_lvalue_reference::type &reference; + typedef typename std::add_lvalue_reference::type>::type &const_reference; + + pointer address(reference r) const RAPIDJSON_NOEXCEPT + { + return std::addressof(r); + } + const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT + { + return std::addressof(r); + } + + size_type max_size() const RAPIDJSON_NOEXCEPT + { + return traits_type::max_size(*this); + } + + template + void construct(pointer p, Args&&... args) + { + traits_type::construct(*this, p, std::forward(args)...); + } + void destroy(pointer p) + { + traits_type::destroy(*this, p); + } + +#else // !RAPIDJSON_HAS_CXX11 + + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + + pointer address(reference r) const RAPIDJSON_NOEXCEPT + { + return allocator_type::address(r); + } + const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT + { + return allocator_type::address(r); + } + + size_type max_size() const RAPIDJSON_NOEXCEPT + { + return allocator_type::max_size(); + } + + void construct(pointer p, const_reference r) + { + allocator_type::construct(p, r); + } + void destroy(pointer p) + { + allocator_type::destroy(p); + } + +#endif // !RAPIDJSON_HAS_CXX11 + + template + U* allocate(size_type n = 1, const void* = 0) + { + return RAPIDJSON_NAMESPACE::Malloc(baseAllocator_, n); + } + template + void deallocate(U* p, size_type n = 1) + { + RAPIDJSON_NAMESPACE::Free(baseAllocator_, p, n); + } + + pointer allocate(size_type n = 1, const void* = 0) + { + return allocate(n); + } + void deallocate(pointer p, size_type n = 1) + { + deallocate(p, n); + } + +#if RAPIDJSON_HAS_CXX11 + using is_always_equal = std::is_empty; +#endif + + template + bool operator==(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT + { + return baseAllocator_ == rhs.baseAllocator_; + } + template + bool operator!=(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT + { + return !operator==(rhs); + } + + //! rapidjson Allocator concept + static const bool kNeedFree = BaseAllocator::kNeedFree; + static const bool kRefCounted = internal::IsRefCounted::Value; + void* Malloc(size_t size) + { + return baseAllocator_.Malloc(size); + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) + { + return baseAllocator_.Realloc(originalPtr, originalSize, newSize); + } + static void Free(void *ptr) RAPIDJSON_NOEXCEPT + { + BaseAllocator::Free(ptr); + } + +private: + template + friend class StdAllocator; // access to StdAllocator.* + + BaseAllocator baseAllocator_; }; +#if !RAPIDJSON_HAS_CXX17 // std::allocator deprecated in C++17 +template +class StdAllocator : + public std::allocator +{ + typedef std::allocator allocator_type; + +public: + typedef BaseAllocator BaseAllocatorType; + + StdAllocator() RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_() + { } + + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + template + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + /* implicit */ + StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(baseAllocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template + struct rebind { + typedef StdAllocator other; + }; + + typedef typename allocator_type::value_type value_type; + +private: + template + friend class StdAllocator; // access to StdAllocator.* + + BaseAllocator baseAllocator_; +}; +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + RAPIDJSON_NAMESPACE_END #endif // RAPIDJSON_ENCODINGS_H_ diff --git a/contrib/rapidjson/include/rapidjson/document.h b/contrib/rapidjson/include/rapidjson/document.h index 028235ec6..f183749ad 100644 --- a/contrib/rapidjson/include/rapidjson/document.h +++ b/contrib/rapidjson/include/rapidjson/document.h @@ -42,12 +42,21 @@ RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible lo RAPIDJSON_DIAG_OFF(effc++) #endif // __GNUC__ +#ifdef GetObject +// see https://github.com/Tencent/rapidjson/issues/1448 +// a former included windows.h might have defined a macro called GetObject, which affects +// GetObject defined here. This ensures the macro does not get applied +#pragma push_macro("GetObject") +#define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#undef GetObject +#endif + #ifndef RAPIDJSON_NOMEMBERITERATORCLASS #include // std::random_access_iterator_tag #endif -#if RAPIDJSON_HAS_CXX11_RVALUE_REFS -#include // std::move +#if RAPIDJSON_USE_MEMBERSMAP +#include // std::multimap #endif RAPIDJSON_NAMESPACE_BEGIN @@ -66,7 +75,7 @@ class GenericDocument; User can define this to use CrtAllocator or MemoryPoolAllocator. */ #ifndef RAPIDJSON_DEFAULT_ALLOCATOR -#define RAPIDJSON_DEFAULT_ALLOCATOR MemoryPoolAllocator +#define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<::RAPIDJSON_NAMESPACE::CrtAllocator> #endif /*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR @@ -76,7 +85,7 @@ class GenericDocument; User can define this to use CrtAllocator or MemoryPoolAllocator. */ #ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR -#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR CrtAllocator +#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR ::RAPIDJSON_NAMESPACE::CrtAllocator #endif /*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY @@ -732,18 +741,8 @@ public: template GenericValue(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { switch (rhs.GetType()) { - case kObjectType: { - SizeType count = rhs.data_.o.size; - Member* lm = reinterpret_cast(allocator.Malloc(count * sizeof(Member))); - const typename GenericValue::Member* rm = rhs.GetMembersPointer(); - for (SizeType i = 0; i < count; i++) { - new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings); - new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings); - } - data_.f.flags = kObjectFlag; - data_.o.size = data_.o.capacity = count; - SetMembersPointer(lm); - } + case kObjectType: + DoCopyMembers(rhs, allocator, copyConstStrings); break; case kArrayType: { SizeType count = rhs.data_.a.size; @@ -879,25 +878,30 @@ public: /*! Need to destruct elements of array, members of object, or copy-string. */ ~GenericValue() { - if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + // With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release + // their Allocator if it's refcounted (e.g. MemoryPoolAllocator). + if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 && + internal::IsRefCounted::Value)) { switch(data_.f.flags) { case kArrayFlag: { GenericValue* e = GetElementsPointer(); for (GenericValue* v = e; v != e + data_.a.size; ++v) v->~GenericValue(); - Allocator::Free(e); + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Allocator::Free(e); + } } break; case kObjectFlag: - for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) - m->~Member(); - Allocator::Free(GetMembersPointer()); + DoFreeMembers(); break; case kCopyStringFlag: - Allocator::Free(const_cast(GetStringPointer())); + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Allocator::Free(const_cast(GetStringPointer())); + } break; default: @@ -916,8 +920,13 @@ public: */ GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { if (RAPIDJSON_LIKELY(this != &rhs)) { + // Can't destroy "this" before assigning "rhs", otherwise "rhs" + // could be used after free if it's an sub-Value of "this", + // hence the temporary danse. + GenericValue temp; + temp.RawAssign(rhs); this->~GenericValue(); - RawAssign(rhs); + RawAssign(temp); } return *this; } @@ -1024,7 +1033,7 @@ public: return false; for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); - if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + if (rhsMemberItr == rhs.MemberEnd() || (!(lhsMemberItr->value == rhsMemberItr->value))) return false; } return true; @@ -1033,7 +1042,7 @@ public: if (data_.a.size != rhs.data_.a.size) return false; for (SizeType i = 0; i < data_.a.size; i++) - if ((*this)[i] != rhs[i]) + if (!((*this)[i] == rhs[i])) return false; return true; @@ -1069,6 +1078,7 @@ public: */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } +#ifndef __cpp_impl_three_way_comparison //! Not-equal-to operator /*! \return !(*this == rhs) */ @@ -1093,6 +1103,7 @@ public: */ template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } //@} +#endif //!@name Type //@{ @@ -1219,13 +1230,28 @@ public: else { RAPIDJSON_ASSERT(false); // see above note - // This will generate -Wexit-time-destructors in clang - // static GenericValue NullValue; - // return NullValue; - - // Use static buffer and placement-new to prevent destruction - static char buffer[sizeof(GenericValue)]; +#if RAPIDJSON_HAS_CXX11 + // Use thread-local storage to prevent races between threads. + // Use static buffer and placement-new to prevent destruction, with + // alignas() to ensure proper alignment. + alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)]; return *new (buffer) GenericValue(); +#elif defined(_MSC_VER) && _MSC_VER < 1900 + // There's no way to solve both thread locality and proper alignment + // simultaneously. + __declspec(thread) static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); +#elif defined(__GNUC__) || defined(__clang__) + // This will generate -Wexit-time-destructors in clang, but that's + // better than having under-alignment. + __thread static GenericValue buffer; + return buffer; +#else + // Don't know what compiler this is, so don't know how to ensure + // thread-locality. + static GenericValue buffer; + return buffer; +#endif } } template @@ -1258,10 +1284,7 @@ public: */ GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) { RAPIDJSON_ASSERT(IsObject()); - if (newCapacity > data_.o.capacity) { - SetMembersPointer(reinterpret_cast(allocator.Realloc(GetMembersPointer(), data_.o.capacity * sizeof(Member), newCapacity * sizeof(Member)))); - data_.o.capacity = newCapacity; - } + DoReserveMembers(newCapacity, allocator); return *this; } @@ -1335,11 +1358,7 @@ public: MemberIterator FindMember(const GenericValue& name) { RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(name.IsString()); - MemberIterator member = MemberBegin(); - for ( ; member != MemberEnd(); ++member) - if (name.StringEqual(member->name)) - break; - return member; + return DoFindMember(name); } template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } @@ -1368,14 +1387,7 @@ public: GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(name.IsString()); - - ObjectData& o = data_.o; - if (o.size >= o.capacity) - MemberReserve(o.capacity == 0 ? kDefaultObjectCapacity : (o.capacity + (o.capacity + 1) / 2), allocator); - Member* members = GetMembersPointer(); - members[o.size].name.RawAssign(name); - members[o.size].value.RawAssign(value); - o.size++; + DoAddMember(name, value, allocator); return *this; } @@ -1509,9 +1521,7 @@ public: */ void RemoveAllMembers() { RAPIDJSON_ASSERT(IsObject()); - for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) - m->~Member(); - data_.o.size = 0; + DoClearMembers(); } //! Remove a member in object by its name. @@ -1555,14 +1565,7 @@ public: RAPIDJSON_ASSERT(data_.o.size > 0); RAPIDJSON_ASSERT(GetMembersPointer() != 0); RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); - - MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); - if (data_.o.size > 1 && m != last) - *m = *last; // Move the last one to this place - else - m->~Member(); // Only one left, just destroy - --data_.o.size; - return m; + return DoRemoveMember(m); } //! Remove a member from an object by iterator. @@ -1594,13 +1597,7 @@ public: RAPIDJSON_ASSERT(first >= MemberBegin()); RAPIDJSON_ASSERT(first <= last); RAPIDJSON_ASSERT(last <= MemberEnd()); - - MemberIterator pos = MemberBegin() + (first - MemberBegin()); - for (MemberIterator itr = pos; itr != last; ++itr) - itr->~Member(); - std::memmove(static_cast(&*pos), &*last, static_cast(MemberEnd() - last) * sizeof(Member)); - data_.o.size -= static_cast(last - first); - return pos; + return DoEraseMembers(first, last); } //! Erase a member in object by its name. @@ -1629,7 +1626,9 @@ public: } Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + ConstObject GetObj() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } //@} @@ -1851,12 +1850,12 @@ public: //!@name String //@{ - const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); } //! Get the length of string. /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). */ - SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); } //! Set this value as a string without copying source string. /*! This version has better performance with supplied length, and also support string containing null character. @@ -1967,7 +1966,7 @@ public: case kArrayType: if (RAPIDJSON_UNLIKELY(!handler.StartArray())) return false; - for (const GenericValue* v = Begin(); v != End(); ++v) + for (ConstValueIterator v = Begin(); v != End(); ++v) if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) return false; return handler.EndArray(data_.a.size); @@ -2105,6 +2104,13 @@ private: Flag f; }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) { + return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str); + } + static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) { + return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length; + } + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } @@ -2112,6 +2118,286 @@ private: RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } +#if RAPIDJSON_USE_MEMBERSMAP + + struct MapTraits { + struct Less { + bool operator()(const Data& s1, const Data& s2) const { + SizeType n1 = DataStringLength(s1), n2 = DataStringLength(s2); + int cmp = std::memcmp(DataString(s1), DataString(s2), sizeof(Ch) * (n1 < n2 ? n1 : n2)); + return cmp < 0 || (cmp == 0 && n1 < n2); + } + }; + typedef std::pair Pair; + typedef std::multimap > Map; + typedef typename Map::iterator Iterator; + }; + typedef typename MapTraits::Map Map; + typedef typename MapTraits::Less MapLess; + typedef typename MapTraits::Pair MapPair; + typedef typename MapTraits::Iterator MapIterator; + + // + // Layout of the members' map/array, re(al)located according to the needed capacity: + // + // {Map*}<>{capacity}<>{Member[capacity]}<>{MapIterator[capacity]} + // + // (where <> stands for the RAPIDJSON_ALIGN-ment, if needed) + // + + static RAPIDJSON_FORCEINLINE size_t GetMapLayoutSize(SizeType capacity) { + return RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType)) + + RAPIDJSON_ALIGN(capacity * sizeof(Member)) + + capacity * sizeof(MapIterator); + } + + static RAPIDJSON_FORCEINLINE SizeType &GetMapCapacity(Map* &map) { + return *reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) { + return reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType))); + } + + static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) { + return reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType)) + + RAPIDJSON_ALIGN(GetMapCapacity(map) * sizeof(Member))); + } + + static RAPIDJSON_FORCEINLINE Map* &GetMap(Member* members) { + RAPIDJSON_ASSERT(members != 0); + return *reinterpret_cast(reinterpret_cast(members) - + RAPIDJSON_ALIGN(sizeof(SizeType)) - + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + // Some compilers' debug mechanisms want all iterators to be destroyed, for their accounting.. + RAPIDJSON_FORCEINLINE MapIterator DropMapIterator(MapIterator& rhs) { +#if RAPIDJSON_HAS_CXX11 + MapIterator ret = std::move(rhs); +#else + MapIterator ret = rhs; +#endif + rhs.~MapIterator(); + return ret; + } + + Map* &DoReallocMap(Map** oldMap, SizeType newCapacity, Allocator& allocator) { + Map **newMap = static_cast(allocator.Malloc(GetMapLayoutSize(newCapacity))); + GetMapCapacity(*newMap) = newCapacity; + if (!oldMap) { + *newMap = new (allocator.Malloc(sizeof(Map))) Map(MapLess(), allocator); + } + else { + *newMap = *oldMap; + size_t count = (*oldMap)->size(); + std::memcpy(static_cast(GetMapMembers(*newMap)), + static_cast(GetMapMembers(*oldMap)), + count * sizeof(Member)); + MapIterator *oldIt = GetMapIterators(*oldMap), + *newIt = GetMapIterators(*newMap); + while (count--) { + new (&newIt[count]) MapIterator(DropMapIterator(oldIt[count])); + } + Allocator::Free(oldMap); + } + return *newMap; + } + + RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { + return GetMapMembers(DoReallocMap(0, capacity, allocator)); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* oldMembers = GetMembersPointer(); + Map **oldMap = oldMembers ? &GetMap(oldMembers) : 0, + *&newMap = DoReallocMap(oldMap, newCapacity, allocator); + RAPIDJSON_SETPOINTER(Member, o.members, GetMapMembers(newMap)); + o.capacity = newCapacity; + } + } + + template + MemberIterator DoFindMember(const GenericValue& name) { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator mit = map->find(reinterpret_cast(name.data_)); + if (mit != map->end()) { + return MemberIterator(&members[mit->second]); + } + } + return MemberEnd(); + } + + void DoClearMembers() { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + for (SizeType i = 0; i < data_.o.size; i++) { + map->erase(DropMapIterator(mit[i])); + members[i].~Member(); + } + data_.o.size = 0; + } + } + + void DoFreeMembers() { + if (Member* members = GetMembersPointer()) { + GetMap(members)->~Map(); + for (SizeType i = 0; i < data_.o.size; i++) { + members[i].~Member(); + } + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Map** map = &GetMap(members); + Allocator::Free(*map); + Allocator::Free(map); + } + } + } + +#else // !RAPIDJSON_USE_MEMBERSMAP + + RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { + return Malloc(allocator, capacity); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* newMembers = Realloc(allocator, GetMembersPointer(), o.capacity, newCapacity); + RAPIDJSON_SETPOINTER(Member, o.members, newMembers); + o.capacity = newCapacity; + } + } + + template + MemberIterator DoFindMember(const GenericValue& name) { + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + + void DoClearMembers() { + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + void DoFreeMembers() { + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(GetMembersPointer()); + } + +#endif // !RAPIDJSON_USE_MEMBERSMAP + + void DoAddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + ObjectData& o = data_.o; + if (o.size >= o.capacity) + DoReserveMembers(o.capacity ? (o.capacity + (o.capacity + 1) / 2) : kDefaultObjectCapacity, allocator); + Member* members = GetMembersPointer(); + Member* m = members + o.size; + m->name.RawAssign(name); + m->value.RawAssign(value); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + new (&mit[o.size]) MapIterator(map->insert(MapPair(m->name.data_, o.size))); +#endif + ++o.size; + } + + MemberIterator DoRemoveMember(MemberIterator m) { + ObjectData& o = data_.o; + Member* members = GetMembersPointer(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + SizeType mpos = static_cast(&*m - members); + map->erase(DropMapIterator(mit[mpos])); +#endif + MemberIterator last(members + (o.size - 1)); + if (o.size > 1 && m != last) { +#if RAPIDJSON_USE_MEMBERSMAP + new (&mit[mpos]) MapIterator(DropMapIterator(mit[&*last - members])); + mit[mpos]->second = mpos; +#endif + *m = *last; // Move the last one to this place + } + else { + m->~Member(); // Only one left, just destroy + } + --o.size; + return m; + } + + MemberIterator DoEraseMembers(ConstMemberIterator first, ConstMemberIterator last) { + ObjectData& o = data_.o; + MemberIterator beg = MemberBegin(), + pos = beg + (first - beg), + end = MemberEnd(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(GetMembersPointer()); + MapIterator* mit = GetMapIterators(map); +#endif + for (MemberIterator itr = pos; itr != last; ++itr) { +#if RAPIDJSON_USE_MEMBERSMAP + map->erase(DropMapIterator(mit[itr - beg])); +#endif + itr->~Member(); + } +#if RAPIDJSON_USE_MEMBERSMAP + if (first != last) { + // Move remaining members/iterators + MemberIterator next = pos + (last - first); + for (MemberIterator itr = pos; next != end; ++itr, ++next) { + std::memcpy(static_cast(&*itr), &*next, sizeof(Member)); + SizeType mpos = static_cast(itr - beg); + new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg])); + mit[mpos]->second = mpos; + } + } +#else + std::memmove(static_cast(&*pos), &*last, + static_cast(end - last) * sizeof(Member)); +#endif + o.size -= static_cast(last - first); + return pos; + } + + template + void DoCopyMembers(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings) { + RAPIDJSON_ASSERT(rhs.GetType() == kObjectType); + + data_.f.flags = kObjectFlag; + SizeType count = rhs.data_.o.size; + Member* lm = DoAllocMembers(count, allocator); + const typename GenericValue::Member* rm = rhs.GetMembersPointer(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(lm); + MapIterator* mit = GetMapIterators(map); +#endif + for (SizeType i = 0; i < count; i++) { + new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings); + new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings); +#if RAPIDJSON_USE_MEMBERSMAP + new (&mit[i]) MapIterator(map->insert(MapPair(lm[i].name.data_, i))); +#endif + } + data_.o.size = data_.o.capacity = count; + SetMembersPointer(lm); + } + // Initialize this value as array with initial data, without calling destructor. void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { data_.f.flags = kArrayFlag; @@ -2129,9 +2415,16 @@ private: void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { data_.f.flags = kObjectFlag; if (count) { - Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); + Member* m = DoAllocMembers(count, allocator); SetMembersPointer(m); std::memcpy(static_cast(m), members, count * sizeof(Member)); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(m); + MapIterator* mit = GetMapIterators(map); + for (SizeType i = 0; i < count; i++) { + new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i))); + } +#endif } else SetMembersPointer(0); @@ -2208,6 +2501,7 @@ public: typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. typedef GenericValue ValueType; //!< Value type of the document. typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef StackAllocator StackAllocatorType; //!< StackAllocator type from template parameter. //! Constructor /*! Creates an empty document of specified type. @@ -2252,6 +2546,13 @@ public: #endif ~GenericDocument() { + // Clear the ::ValueType before ownAllocator is destroyed, ~ValueType() + // runs last and may access its elements or members which would be freed + // with an allocator like MemoryPoolAllocator (CrtAllocator does not + // free its data when destroyed, but MemoryPoolAllocator does). + if (ownAllocator_) { + ValueType::SetNull(); + } Destroy(); } @@ -2734,4 +3035,9 @@ private: RAPIDJSON_NAMESPACE_END RAPIDJSON_DIAG_POP +#ifdef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#pragma pop_macro("GetObject") +#undef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#endif + #endif // RAPIDJSON_DOCUMENT_H_ diff --git a/contrib/rapidjson/include/rapidjson/error/en.h b/contrib/rapidjson/include/rapidjson/error/en.h index 5d2e57b7f..c87b04eb1 100644 --- a/contrib/rapidjson/include/rapidjson/error/en.h +++ b/contrib/rapidjson/include/rapidjson/error/en.h @@ -1,5 +1,5 @@ // Tencent is pleased to support the open source community by making RapidJSON available. -// +// // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. // // Licensed under the MIT License (the "License"); you may not use this file except @@ -7,9 +7,9 @@ // // http://opensource.org/licenses/MIT // -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #ifndef RAPIDJSON_ERROR_EN_H_ @@ -39,13 +39,13 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); - + case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); - + case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); - + case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); @@ -104,15 +104,69 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode val case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'."); case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors."); - case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'."); + case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf', indices '%matches'."); case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors."); case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors."); case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'."); + case kValidateErrorReadOnly: return RAPIDJSON_ERROR_STRING("Property is read-only but has been provided when validation is for writing."); + case kValidateErrorWriteOnly: return RAPIDJSON_ERROR_STRING("Property is write-only but has been provided when validation is for reading."); + default: return RAPIDJSON_ERROR_STRING("Unknown error."); } } +//! Maps error code of schema document compilation into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param schemaErrorCode Error code obtained from compiling the schema document. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ + inline const RAPIDJSON_ERROR_CHARTYPE* GetSchemaError_En(SchemaErrorCode schemaErrorCode) { + switch (schemaErrorCode) { + case kSchemaErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kSchemaErrorStartUnknown: return RAPIDJSON_ERROR_STRING("Pointer '%value' to start of schema does not resolve to a location in the document."); + case kSchemaErrorRefPlainName: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' must be a JSON pointer."); + case kSchemaErrorRefInvalid: return RAPIDJSON_ERROR_STRING("$ref must not be an empty string."); + case kSchemaErrorRefPointerInvalid: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' is not a valid JSON pointer at offset '%offset'."); + case kSchemaErrorRefUnknown: return RAPIDJSON_ERROR_STRING("$ref '%value' does not resolve to a location in the target document."); + case kSchemaErrorRefCyclical: return RAPIDJSON_ERROR_STRING("$ref '%value' is cyclical."); + case kSchemaErrorRefNoRemoteProvider: return RAPIDJSON_ERROR_STRING("$ref is remote but there is no remote provider."); + case kSchemaErrorRefNoRemoteSchema: return RAPIDJSON_ERROR_STRING("$ref '%value' is remote but the remote provider did not return a schema."); + case kSchemaErrorRegexInvalid: return RAPIDJSON_ERROR_STRING("Invalid regular expression '%value' in 'pattern' or 'patternProperties'."); + case kSchemaErrorSpecUnknown: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not recognized."); + case kSchemaErrorSpecUnsupported: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not supported."); + case kSchemaErrorSpecIllegal: return RAPIDJSON_ERROR_STRING("Both JSON schema draft and OpenAPI version found in document."); + case kSchemaErrorReadOnlyAndWriteOnly: return RAPIDJSON_ERROR_STRING("Property must not be both 'readOnly' and 'writeOnly'."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } + } + +//! Maps error code of pointer parse into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param pointerParseErrorCode Error code obtained from pointer parse. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetPointerParseError_En(PointerParseErrorCode pointerParseErrorCode) { + switch (pointerParseErrorCode) { + case kPointerParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kPointerParseErrorTokenMustBeginWithSolidus: return RAPIDJSON_ERROR_STRING("A token must begin with a '/'."); + case kPointerParseErrorInvalidEscape: return RAPIDJSON_ERROR_STRING("Invalid escape."); + case kPointerParseErrorInvalidPercentEncoding: return RAPIDJSON_ERROR_STRING("Invalid percent encoding in URI fragment."); + case kPointerParseErrorCharacterMustPercentEncode: return RAPIDJSON_ERROR_STRING("A character must be percent encoded in a URI fragment."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + RAPIDJSON_NAMESPACE_END #ifdef __clang__ diff --git a/contrib/rapidjson/include/rapidjson/error/error.h b/contrib/rapidjson/include/rapidjson/error/error.h index 6270da11a..cae345db3 100644 --- a/contrib/rapidjson/include/rapidjson/error/error.h +++ b/contrib/rapidjson/include/rapidjson/error/error.h @@ -1,5 +1,5 @@ // Tencent is pleased to support the open source community by making RapidJSON available. -// +// // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. // // Licensed under the MIT License (the "License"); you may not use this file except @@ -7,9 +7,9 @@ // // http://opensource.org/licenses/MIT // -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #ifndef RAPIDJSON_ERROR_ERROR_H_ @@ -42,7 +42,7 @@ RAPIDJSON_DIAG_OFF(padded) /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_ERROR_STRING -//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. +//! Macro for converting string literal to \ref RAPIDJSON_ERROR_CHARTYPE[]. /*! \ingroup RAPIDJSON_ERRORS By default this conversion macro does nothing. On Windows, user can define this macro as \c _T(x) for supporting both @@ -185,14 +185,17 @@ enum ValidateErrorCode { kValidateErrorPatternProperties, //!< See other errors. kValidateErrorDependencies, //!< Object has missing property or schema dependencies. - kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values - kValidateErrorType, //!< Property has a type that is not allowed by the schema.. + kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values. + kValidateErrorType, //!< Property has a type that is not allowed by the schema. kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'. kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'. kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'. kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'. - kValidateErrorNot //!< Property matched the sub-schema specified by 'not'. + kValidateErrorNot, //!< Property matched the sub-schema specified by 'not'. + + kValidateErrorReadOnly, //!< Property is read-only but has been provided when validation is for writing + kValidateErrorWriteOnly //!< Property is write-only but has been provided when validation is for reading }; //! Function pointer type of GetValidateError(). @@ -207,6 +210,72 @@ enum ValidateErrorCode { */ typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode); +/////////////////////////////////////////////////////////////////////////////// +// SchemaErrorCode + +//! Error codes when validating. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericSchemaValidator +*/ +enum SchemaErrorCode { + kSchemaErrorNone = 0, //!< No error. + + kSchemaErrorStartUnknown, //!< Pointer to start of schema does not resolve to a location in the document + kSchemaErrorRefPlainName, //!< $ref fragment must be a JSON pointer + kSchemaErrorRefInvalid, //!< $ref must not be an empty string + kSchemaErrorRefPointerInvalid, //!< $ref fragment is not a valid JSON pointer at offset + kSchemaErrorRefUnknown, //!< $ref does not resolve to a location in the target document + kSchemaErrorRefCyclical, //!< $ref is cyclical + kSchemaErrorRefNoRemoteProvider, //!< $ref is remote but there is no remote provider + kSchemaErrorRefNoRemoteSchema, //!< $ref is remote but the remote provider did not return a schema + kSchemaErrorRegexInvalid, //!< Invalid regular expression in 'pattern' or 'patternProperties' + kSchemaErrorSpecUnknown, //!< JSON schema draft or OpenAPI version is not recognized + kSchemaErrorSpecUnsupported, //!< JSON schema draft or OpenAPI version is not supported + kSchemaErrorSpecIllegal, //!< Both JSON schema draft and OpenAPI version found in document + kSchemaErrorReadOnlyAndWriteOnly //!< Property must not be both 'readOnly' and 'writeOnly' +}; + +//! Function pointer type of GetSchemaError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetSchemaError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetSchemaErrorFunc GetSchemaError = GetSchemaError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetSchemaError(validator.GetInvalidSchemaCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetSchemaErrorFunc)(SchemaErrorCode); + +/////////////////////////////////////////////////////////////////////////////// +// PointerParseErrorCode + +//! Error code of JSON pointer parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode +*/ +enum PointerParseErrorCode { + kPointerParseErrorNone = 0, //!< The parse is successful + + kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' + kPointerParseErrorInvalidEscape, //!< Invalid escape + kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment + kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment +}; + +//! Function pointer type of GetPointerParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetPointerParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetPointerParseErrorFunc GetPointerParseError = GetPointerParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetPointerParseError(pointer.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetPointerParseErrorFunc)(PointerParseErrorCode); + + RAPIDJSON_NAMESPACE_END #ifdef __clang__ diff --git a/contrib/rapidjson/include/rapidjson/internal/biginteger.h b/contrib/rapidjson/include/rapidjson/internal/biginteger.h index 12455788f..4930043dc 100644 --- a/contrib/rapidjson/include/rapidjson/internal/biginteger.h +++ b/contrib/rapidjson/include/rapidjson/internal/biginteger.h @@ -19,7 +19,11 @@ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64) #include // for _umul128 +#if !defined(_ARM64EC_) #pragma intrinsic(_umul128) +#else +#pragma comment(lib,"softintrin") +#endif #endif RAPIDJSON_NAMESPACE_BEGIN @@ -37,7 +41,8 @@ public: digits_[0] = u; } - BigInteger(const char* decimals, size_t length) : count_(1) { + template + BigInteger(const Ch* decimals, size_t length) : count_(1) { RAPIDJSON_ASSERT(length > 0); digits_[0] = 0; size_t i = 0; @@ -221,7 +226,8 @@ public: bool IsZero() const { return count_ == 1 && digits_[0] == 0; } private: - void AppendDecimal64(const char* begin, const char* end) { + template + void AppendDecimal64(const Ch* begin, const Ch* end) { uint64_t u = ParseUint64(begin, end); if (IsZero()) *this = u; @@ -236,11 +242,12 @@ private: digits_[count_++] = digit; } - static uint64_t ParseUint64(const char* begin, const char* end) { + template + static uint64_t ParseUint64(const Ch* begin, const Ch* end) { uint64_t r = 0; - for (const char* p = begin; p != end; ++p) { - RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); - r = r * 10u + static_cast(*p - '0'); + for (const Ch* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9')); + r = r * 10u + static_cast(*p - Ch('0')); } return r; } @@ -252,7 +259,7 @@ private: if (low < k) (*outHigh)++; return low; -#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) __extension__ typedef unsigned __int128 uint128; uint128 p = static_cast(a) * static_cast(b); p += k; diff --git a/contrib/rapidjson/include/rapidjson/internal/diyfp.h b/contrib/rapidjson/include/rapidjson/internal/diyfp.h index a40797ec2..1f60fb60c 100644 --- a/contrib/rapidjson/include/rapidjson/internal/diyfp.h +++ b/contrib/rapidjson/include/rapidjson/internal/diyfp.h @@ -25,7 +25,11 @@ #if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) #include +#if !defined(_ARM64EC_) #pragma intrinsic(_umul128) +#else +#pragma comment(lib,"softintrin") +#endif #endif RAPIDJSON_NAMESPACE_BEGIN @@ -75,7 +79,7 @@ struct DiyFp { if (l & (uint64_t(1) << 63)) // rounding h++; return DiyFp(h, e + rhs.e + 64); -#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) __extension__ typedef unsigned __int128 uint128; uint128 p = static_cast(f) * static_cast(rhs.f); uint64_t h = static_cast(p >> 64); diff --git a/contrib/rapidjson/include/rapidjson/internal/dtoa.h b/contrib/rapidjson/include/rapidjson/internal/dtoa.h index 621402fd3..cd456721a 100644 --- a/contrib/rapidjson/include/rapidjson/internal/dtoa.h +++ b/contrib/rapidjson/include/rapidjson/internal/dtoa.h @@ -58,7 +58,11 @@ inline int CountDecimalDigit32(uint32_t n) { } inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { - static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + static const uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL, + 1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL, + 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, + 10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL, + 10000000000000000000ULL }; const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); const DiyFp wp_w = Mp - W; uint32_t p1 = static_cast(Mp.f >> -one.e); @@ -86,7 +90,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff uint64_t tmp = (static_cast(p1) << -one.e) + p2; if (tmp <= delta) { *K += kappa; - GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); + GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f); return; } } @@ -103,7 +107,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff if (p2 < delta) { *K += kappa; int index = -kappa; - GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0)); return; } } diff --git a/contrib/rapidjson/include/rapidjson/internal/regex.h b/contrib/rapidjson/include/rapidjson/internal/regex.h index 6446c403a..7740dcd52 100644 --- a/contrib/rapidjson/include/rapidjson/internal/regex.h +++ b/contrib/rapidjson/include/rapidjson/internal/regex.h @@ -615,7 +615,7 @@ public: RAPIDJSON_ASSERT(regex_.IsValid()); if (!allocator_) ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); - stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); + stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); state0_.template Reserve(regex_.stateCount_); state1_.template Reserve(regex_.stateCount_); } diff --git a/contrib/rapidjson/include/rapidjson/internal/strfunc.h b/contrib/rapidjson/include/rapidjson/internal/strfunc.h index baecb6cc8..b698a8f43 100644 --- a/contrib/rapidjson/include/rapidjson/internal/strfunc.h +++ b/contrib/rapidjson/include/rapidjson/internal/strfunc.h @@ -45,6 +45,20 @@ inline SizeType StrLen(const wchar_t* s) { return SizeType(std::wcslen(s)); } +//! Custom strcmpn() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s1 Null-terminated input string. + \param s2 Null-terminated input string. + \return 0 if equal +*/ +template +inline int StrCmp(const Ch* s1, const Ch* s2) { + RAPIDJSON_ASSERT(s1 != 0); + RAPIDJSON_ASSERT(s2 != 0); + while(*s1 && (*s1 == *s2)) { s1++; s2++; } + return static_cast(*s1) < static_cast(*s2) ? -1 : static_cast(*s1) > static_cast(*s2); +} + //! Returns number of code points in a encoded string. template bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { diff --git a/contrib/rapidjson/include/rapidjson/internal/strtod.h b/contrib/rapidjson/include/rapidjson/internal/strtod.h index d61a67a49..55f0e380b 100644 --- a/contrib/rapidjson/include/rapidjson/internal/strtod.h +++ b/contrib/rapidjson/include/rapidjson/internal/strtod.h @@ -128,17 +128,18 @@ inline bool StrtodFast(double d, int p, double* result) { } // Compute an approximation and see if it is within 1/2 ULP -inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) { +template +inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) { uint64_t significand = 0; int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 for (; i < dLen; i++) { if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || - (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5'))) break; - significand = significand * 10u + static_cast(decimals[i] - '0'); + significand = significand * 10u + static_cast(decimals[i] - Ch('0')); } - if (i < dLen && decimals[i] >= '5') // Rounding + if (i < dLen && decimals[i] >= Ch('5')) // Rounding significand++; int remaining = dLen - i; @@ -205,7 +206,8 @@ inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); } -inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) { +template +inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) { RAPIDJSON_ASSERT(dLen >= 0); const BigInteger dInt(decimals, static_cast(dLen)); Double a(approx); @@ -223,7 +225,8 @@ inline double StrtodBigInteger(double approx, const char* decimals, int dLen, in return a.NextPositiveDouble(); } -inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { +template +inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) { RAPIDJSON_ASSERT(d >= 0.0); RAPIDJSON_ASSERT(length >= 1); diff --git a/contrib/rapidjson/include/rapidjson/pointer.h b/contrib/rapidjson/include/rapidjson/pointer.h index 90e5903bc..6f4ef3892 100644 --- a/contrib/rapidjson/include/rapidjson/pointer.h +++ b/contrib/rapidjson/include/rapidjson/pointer.h @@ -16,7 +16,9 @@ #define RAPIDJSON_POINTER_H_ #include "document.h" +#include "uri.h" #include "internal/itoa.h" +#include "error/error.h" // PointerParseErrorCode #ifdef __clang__ RAPIDJSON_DIAG_PUSH @@ -30,19 +32,6 @@ RAPIDJSON_NAMESPACE_BEGIN static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token -//! Error code of parsing. -/*! \ingroup RAPIDJSON_ERRORS - \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode -*/ -enum PointerParseErrorCode { - kPointerParseErrorNone = 0, //!< The parse is successful - - kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' - kPointerParseErrorInvalidEscape, //!< Invalid escape - kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment - kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment -}; - /////////////////////////////////////////////////////////////////////////////// // GenericPointer @@ -68,10 +57,10 @@ enum PointerParseErrorCode { supplied tokens eliminates these. GenericPointer depends on GenericDocument and GenericValue. - + \tparam ValueType The value type of the DOM tree. E.g. GenericValue > \tparam Allocator The allocator type for allocating memory for internal representation. - + \note GenericPointer uses same encoding of ValueType. However, Allocator of GenericPointer is independent of Allocator of Value. */ @@ -80,8 +69,10 @@ class GenericPointer { public: typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value typedef typename ValueType::Ch Ch; //!< Character type from Value + typedef GenericUri UriType; - //! A token is the basic units of internal representation. + + //! A token is the basic units of internal representation. /*! A JSON pointer string representation "/foo/123" is parsed to two tokens: "foo" and 123. 123 will be represented in both numeric form and string form. @@ -163,7 +154,7 @@ public: GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} //! Copy constructor. - GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { *this = rhs; } @@ -520,6 +511,70 @@ public: //@} + //!@name Compute URI + //@{ + + //! Compute the in-scope URI for a subtree. + // For use with JSON pointers into JSON schema documents. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param rootUri Root URI + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \param allocator Allocator for Uris + \return Uri if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a URI cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. + */ + UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { + static const Ch kIdString[] = { 'i', 'd', '\0' }; + static const ValueType kIdValue(kIdString, 2); + UriType base = UriType(rootUri, allocator); + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + // See if we have an id, and if so resolve with the current base + typename ValueType::MemberIterator m = v->FindMember(kIdValue); + if (m != v->MemberEnd() && (m->value).IsString()) { + UriType here = UriType(m->value, allocator).Resolve(base, allocator); + base = here; + } + m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + break; + v = &m->value; + } + continue; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + break; + v = &((*v)[t->index]); + continue; + default: + break; + } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast(t - tokens_); + return UriType(allocator); + } + return base; + } + + UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { + return GetUri(const_cast(root), rootUri, unresolvedTokenIndex, allocator); + } + + //!@name Query value //@{ @@ -634,7 +689,7 @@ public: ValueType& GetWithDefault(GenericDocument& document, const Ch* defaultValue) const { return GetWithDefault(document, defaultValue, document.GetAllocator()); } - + #if RAPIDJSON_HAS_STDSTRING //! Query a value in a document with default std::basic_string. template @@ -835,10 +890,16 @@ private: std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); } - // Adjust pointers to name buffer - std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; - for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) - t->name += diff; + // The names of each token point to a string in the nameBuffer_. The + // previous memcpy copied over string pointers into the rhs.nameBuffer_, + // but they should point to the strings in the new nameBuffer_. + for (size_t i = 0; i < rhs.tokenCount_; ++i) { + // The offset between the string address and the name buffer should + // still be constant, so we can just get this offset and set each new + // token name according the new buffer start + the known offset. + std::ptrdiff_t name_offset = rhs.tokens_[i].name - rhs.nameBuffer_; + tokens_[i].name = nameBuffer_ + name_offset; + } return nameBuffer_ + nameBufferSize; } @@ -928,7 +989,7 @@ private: } i++; - + // Escaping "~0" -> '~', "~1" -> '/' if (c == '~') { if (i < length) { diff --git a/contrib/rapidjson/include/rapidjson/rapidjson.h b/contrib/rapidjson/include/rapidjson/rapidjson.h index 78aa89a0e..5ea694795 100644 --- a/contrib/rapidjson/include/rapidjson/rapidjson.h +++ b/contrib/rapidjson/include/rapidjson/rapidjson.h @@ -1,5 +1,5 @@ // Tencent is pleased to support the open source community by making RapidJSON available. -// +// // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. // // Licensed under the MIT License (the "License"); you may not use this file except @@ -7,9 +7,9 @@ // // http://opensource.org/licenses/MIT // -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #ifndef RAPIDJSON_RAPIDJSON_H_ @@ -17,7 +17,7 @@ /*!\file rapidjson.h \brief common definitions and configuration - + \see RAPIDJSON_CONFIG */ @@ -124,6 +124,19 @@ #define RAPIDJSON_NAMESPACE_END } #endif +/////////////////////////////////////////////////////////////////////////////// +// __cplusplus macro + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#if defined(_MSC_VER) +#define RAPIDJSON_CPLUSPLUS _MSVC_LANG +#else +#define RAPIDJSON_CPLUSPLUS __cplusplus +#endif + +//!@endcond + /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_HAS_STDSTRING @@ -149,6 +162,24 @@ #include #endif // RAPIDJSON_HAS_STDSTRING +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_USE_MEMBERSMAP + +/*! \def RAPIDJSON_USE_MEMBERSMAP + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for object members handling in a \c std::multimap + + By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object + members are stored in a \c std::multimap for faster lookup and deletion times, a + trade off with a slightly slower insertion time and a small object allocat(or)ed + memory overhead. + + \hideinitializer +*/ +#ifndef RAPIDJSON_USE_MEMBERSMAP +#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default +#endif + /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NO_INT64DEFINE @@ -164,7 +195,7 @@ */ #ifndef RAPIDJSON_NO_INT64DEFINE //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN -#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 #include "msinttypes/stdint.h" #include "msinttypes/inttypes.h" #else @@ -246,7 +277,7 @@ # elif defined(RAPIDJSON_DOXYGEN_RUNNING) # define RAPIDJSON_ENDIAN # else -# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. # endif #endif // RAPIDJSON_ENDIAN @@ -411,7 +442,7 @@ RAPIDJSON_NAMESPACE_END // Prefer C++11 static_assert, if available #ifndef RAPIDJSON_STATIC_ASSERT -#if __cplusplus >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) +#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) #define RAPIDJSON_STATIC_ASSERT(x) \ static_assert(x, RAPIDJSON_STRINGIFY(x)) #endif // C++11 @@ -482,7 +513,7 @@ RAPIDJSON_NAMESPACE_END //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN -#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { #define RAPIDJSON_MULTILINEMACRO_END \ } while((void)0, 0) @@ -541,8 +572,14 @@ RAPIDJSON_NAMESPACE_END /////////////////////////////////////////////////////////////////////////////// // C++11 features +#ifndef RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L) +#endif + #ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS -#if defined(__clang__) +#if RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#elif defined(__clang__) #if __has_feature(cxx_rvalue_references) && \ (defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 @@ -559,8 +596,14 @@ RAPIDJSON_NAMESPACE_END #endif #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + #ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT -#if defined(__clang__) +#if RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#elif defined(__clang__) #define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) || \ @@ -570,11 +613,13 @@ RAPIDJSON_NAMESPACE_END #define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 #endif #endif +#ifndef RAPIDJSON_NOEXCEPT #if RAPIDJSON_HAS_CXX11_NOEXCEPT #define RAPIDJSON_NOEXCEPT noexcept #else -#define RAPIDJSON_NOEXCEPT /* noexcept */ +#define RAPIDJSON_NOEXCEPT throw() #endif // RAPIDJSON_HAS_CXX11_NOEXCEPT +#endif // no automatic detection, yet #ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS @@ -600,9 +645,17 @@ RAPIDJSON_NAMESPACE_END /////////////////////////////////////////////////////////////////////////////// // C++17 features -#if defined(__has_cpp_attribute) -# if __has_cpp_attribute(fallthrough) -# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] +#ifndef RAPIDJSON_HAS_CXX17 +#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L) +#endif + +#if RAPIDJSON_HAS_CXX17 +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] +#elif defined(__has_cpp_attribute) +# if __has_cpp_attribute(clang::fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]] +# elif __has_cpp_attribute(fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough)) # else # define RAPIDJSON_DELIBERATE_FALLTHROUGH # endif @@ -628,12 +681,8 @@ RAPIDJSON_NAMESPACE_END #ifndef RAPIDJSON_NOEXCEPT_ASSERT #ifdef RAPIDJSON_ASSERT_THROWS -#if RAPIDJSON_HAS_CXX11_NOEXCEPT -#define RAPIDJSON_NOEXCEPT_ASSERT(x) -#else #include #define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x) -#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT #else #define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x) #endif // RAPIDJSON_ASSERT_THROWS @@ -682,7 +731,7 @@ enum Type { kFalseType = 1, //!< false kTrueType = 2, //!< true kObjectType = 3, //!< object - kArrayType = 4, //!< array + kArrayType = 4, //!< array kStringType = 5, //!< string kNumberType = 6 //!< number }; diff --git a/contrib/rapidjson/include/rapidjson/reader.h b/contrib/rapidjson/include/rapidjson/reader.h index 09ace4eba..55546601e 100644 --- a/contrib/rapidjson/include/rapidjson/reader.h +++ b/contrib/rapidjson/include/rapidjson/reader.h @@ -1404,11 +1404,11 @@ private: } #endif // RAPIDJSON_NEON - template + template class NumberStream; - template - class NumberStream { + template + class NumberStream { public: typedef typename InputStream::Ch Ch; @@ -1421,7 +1421,7 @@ private: size_t Tell() { return is.Tell(); } size_t Length() { return 0; } - const char* Pop() { return 0; } + const StackCharacter* Pop() { return 0; } protected: NumberStream& operator=(const NumberStream&); @@ -1429,45 +1429,47 @@ private: InputStream& is; }; - template - class NumberStream : public NumberStream { - typedef NumberStream Base; + template + class NumberStream : public NumberStream { + typedef NumberStream Base; public: - NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} + NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {} RAPIDJSON_FORCEINLINE Ch TakePush() { - stackStream.Put(static_cast(Base::is.Peek())); + stackStream.Put(static_cast(Base::is.Peek())); return Base::is.Take(); } - RAPIDJSON_FORCEINLINE void Push(char c) { + RAPIDJSON_FORCEINLINE void Push(StackCharacter c) { stackStream.Put(c); } size_t Length() { return stackStream.Length(); } - const char* Pop() { + const StackCharacter* Pop() { stackStream.Put('\0'); return stackStream.Pop(); } private: - StackStream stackStream; + StackStream stackStream; }; - template - class NumberStream : public NumberStream { - typedef NumberStream Base; + template + class NumberStream : public NumberStream { + typedef NumberStream Base; public: - NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} + NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s) {} RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } }; template void ParseNumber(InputStream& is, Handler& handler) { + typedef typename internal::SelectIf, typename TargetEncoding::Ch, char>::Type NumberCharacter; + internal::StreamLocalCopy copy(is); - NumberStream(s.Length()); - StringStream srcStream(s.Pop()); + GenericStringStream > srcStream(s.Pop()); StackStream dstStream(stack_); while (numCharsToCopy--) { - Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); + Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); } dstStream.Put('\0'); const typename TargetEncoding::Ch* str = dstStream.Pop(); @@ -1705,7 +1707,7 @@ private: } else { size_t length = s.Length(); - const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + const NumberCharacter* decimal = s.Pop(); // Pop stack no matter if it will be used or not. if (useDouble) { int p = exp + expFrac; diff --git a/contrib/rapidjson/include/rapidjson/schema.h b/contrib/rapidjson/include/rapidjson/schema.h index 11f716096..02a6d0f9e 100644 --- a/contrib/rapidjson/include/rapidjson/schema.h +++ b/contrib/rapidjson/include/rapidjson/schema.h @@ -1,5 +1,5 @@ // Tencent is pleased to support the open source community by making RapidJSON available-> -// +// // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved-> // // Licensed under the MIT License (the "License"); you may not use this file except @@ -7,9 +7,9 @@ // // http://opensource->org/licenses/MIT // -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied-> See the License for the +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied-> See the License for the // specific language governing permissions and limitations under the License-> #ifndef RAPIDJSON_SCHEMA_H_ @@ -19,17 +19,14 @@ #include "pointer.h" #include "stringbuffer.h" #include "error/en.h" +#include "uri.h" #include // abs, floor #if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 -#else -#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 #endif -#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) -#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 -#else +#if !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) || !(__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) #define RAPIDJSON_SCHEMA_USE_STDREGEX 0 #endif @@ -49,10 +46,6 @@ #define RAPIDJSON_SCHEMA_VERBOSE 0 #endif -#if RAPIDJSON_SCHEMA_VERBOSE -#include "stringbuffer.h" -#endif - RAPIDJSON_DIAG_PUSH #if defined(__GNUC__) @@ -77,48 +70,94 @@ RAPIDJSON_NAMESPACE_BEGIN namespace internal { -inline void PrintInvalidKeyword(const char* keyword) { - printf("Fail keyword: %s\n", keyword); +inline void PrintInvalidKeywordData(const char* keyword) { + printf(" Fail keyword: '%s'\n", keyword); } -inline void PrintInvalidKeyword(const wchar_t* keyword) { - wprintf(L"Fail keyword: %ls\n", keyword); +inline void PrintInvalidKeywordData(const wchar_t* keyword) { + wprintf(L" Fail keyword: '%ls'\n", keyword); } -inline void PrintInvalidDocument(const char* document) { - printf("Fail document: %s\n\n", document); +inline void PrintInvalidDocumentData(const char* document) { + printf(" Fail document: '%s'\n", document); } -inline void PrintInvalidDocument(const wchar_t* document) { - wprintf(L"Fail document: %ls\n\n", document); +inline void PrintInvalidDocumentData(const wchar_t* document) { + wprintf(L" Fail document: '%ls'\n", document); } -inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) { - printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); +inline void PrintValidatorPointersData(const char* s, const char* d, unsigned depth) { + printf(" Sch: %*s'%s'\n Doc: %*s'%s'\n", depth * 4, " ", s, depth * 4, " ", d); } -inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) { - wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); +inline void PrintValidatorPointersData(const wchar_t* s, const wchar_t* d, unsigned depth) { + wprintf(L" Sch: %*ls'%ls'\n Doc: %*ls'%ls'\n", depth * 4, L" ", s, depth * 4, L" ", d); +} + +inline void PrintSchemaIdsData(const char* base, const char* local, const char* resolved) { + printf(" Resolving id: Base: '%s', Local: '%s', Resolved: '%s'\n", base, local, resolved); +} + +inline void PrintSchemaIdsData(const wchar_t* base, const wchar_t* local, const wchar_t* resolved) { + wprintf(L" Resolving id: Base: '%ls', Local: '%ls', Resolved: '%ls'\n", base, local, resolved); +} + +inline void PrintMethodData(const char* method) { + printf("%s\n", method); +} + +inline void PrintMethodData(const char* method, bool b) { + printf("%s, Data: '%s'\n", method, b ? "true" : "false"); +} + +inline void PrintMethodData(const char* method, int64_t i) { + printf("%s, Data: '%" PRId64 "'\n", method, i); +} + +inline void PrintMethodData(const char* method, uint64_t u) { + printf("%s, Data: '%" PRIu64 "'\n", method, u); +} + +inline void PrintMethodData(const char* method, double d) { + printf("%s, Data: '%lf'\n", method, d); +} + +inline void PrintMethodData(const char* method, const char* s) { + printf("%s, Data: '%s'\n", method, s); +} + +inline void PrintMethodData(const char* method, const wchar_t* s) { + wprintf(L"%hs, Data: '%ls'\n", method, s); +} + +inline void PrintMethodData(const char* method, const char* s1, const char* s2) { + printf("%s, Data: '%s', '%s'\n", method, s1, s2); +} + +inline void PrintMethodData(const char* method, const wchar_t* s1, const wchar_t* s2) { + wprintf(L"%hs, Data: '%ls', '%ls'\n", method, s1, s2); } } // namespace internal #endif // RAPIDJSON_SCHEMA_VERBOSE +#ifndef RAPIDJSON_SCHEMA_PRINT +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_PRINT(name, ...) internal::Print##name##Data(__VA_ARGS__) +#else +#define RAPIDJSON_SCHEMA_PRINT(name, ...) +#endif +#endif + /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_INVALID_KEYWORD_RETURN -#if RAPIDJSON_SCHEMA_VERBOSE -#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword) -#else -#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) -#endif - #define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\ RAPIDJSON_MULTILINEMACRO_BEGIN\ context.invalidCode = code;\ context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\ - RAPIDJSON_INVALID_KEYWORD_VERBOSE(context.invalidKeyword);\ + RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, context.invalidKeyword);\ return false;\ RAPIDJSON_MULTILINEMACRO_END @@ -136,14 +175,56 @@ RAPIDJSON_MULTILINEMACRO_END #endif //! Combination of validate flags -/*! \see - */ enum ValidateFlag { kValidateNoFlags = 0, //!< No flags are set. kValidateContinueOnErrorFlag = 1, //!< Don't stop after first validation error. + kValidateReadFlag = 2, //!< Validation is for a read semantic. + kValidateWriteFlag = 4, //!< Validation is for a write semantic. kValidateDefaultFlags = RAPIDJSON_VALIDATE_DEFAULT_FLAGS //!< Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS }; +/////////////////////////////////////////////////////////////////////////////// +// Specification +enum SchemaDraft { + kDraftUnknown = -1, + kDraftNone = 0, + kDraft03 = 3, + kDraftMin = 4, //!< Current minimum supported draft + kDraft04 = 4, + kDraft05 = 5, + kDraftMax = 5, //!< Current maximum supported draft + kDraft06 = 6, + kDraft07 = 7, + kDraft2019_09 = 8, + kDraft2020_12 = 9 +}; + +enum OpenApiVersion { + kVersionUnknown = -1, + kVersionNone = 0, + kVersionMin = 2, //!< Current minimum supported version + kVersion20 = 2, + kVersion30 = 3, + kVersionMax = 3, //!< Current maximum supported version + kVersion31 = 4, +}; + +struct Specification { + Specification(SchemaDraft d) : draft(d), oapi(kVersionNone) {} + Specification(OpenApiVersion o) : oapi(o) { + if (oapi == kVersion20) draft = kDraft04; + else if (oapi == kVersion30) draft = kDraft05; + else if (oapi == kVersion31) draft = kDraft2020_12; + else draft = kDraft04; + } + ~Specification() {} + bool IsSupported() const { + return ((draft >= kDraftMin && draft <= kDraftMax) && ((oapi == kVersionNone) || (oapi >= kVersionMin && oapi <= kVersionMax))); + } + SchemaDraft draft; + OpenApiVersion oapi; +}; + /////////////////////////////////////////////////////////////////////////////// // Forward declarations @@ -233,8 +314,11 @@ public: virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0; virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0; virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0; - virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched) = 0; + virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void MultipleOneOf(SizeType index1, SizeType index2) = 0; virtual void Disallowed() = 0; + virtual void DisallowedWhenWriting() = 0; + virtual void DisallowedWhenReading() = 0; }; @@ -255,10 +339,10 @@ public: bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } - bool Double(double d) { - Number n; + bool Double(double d) { + Number n; if (d < 0) n.u.i = static_cast(d); - else n.u.u = static_cast(d); + else n.u.u = static_cast(d); n.d = d; return WriteNumber(n); } @@ -279,7 +363,9 @@ public: uint64_t h = Hash(0, kObjectType); uint64_t* kv = stack_.template Pop(memberCount * 2); for (SizeType i = 0; i < memberCount; i++) - h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive + // Issue #2205 + // Hasing the key to avoid key=value cases with bug-prone zero-value hash + h ^= Hash(Hash(0, kv[i * 2]), kv[i * 2 + 1]); // Use xor to achieve member order insensitive *stack_.template Push() = h; return true; } @@ -317,7 +403,7 @@ private: bool WriteBuffer(Type type, const void* data, size_t len) { // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ - uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); + uint64_t h = Hash(RAPIDJSON_UINT64_C2(0xcbf29ce4, 0x84222325), type); const unsigned char* d = static_cast(data); for (size_t i = 0; i < len; i++) h = Hash(h, d[i]); @@ -352,10 +438,11 @@ struct SchemaValidationContext { kPatternValidatorWithAdditionalProperty }; - SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) : + SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s, unsigned fl = 0) : factory(f), error_handler(eh), schema(s), + flags(fl), valueSchema(), invalidKeyword(), invalidCode(), @@ -379,13 +466,19 @@ struct SchemaValidationContext { if (hasher) factory.DestroryHasher(hasher); if (validators) { - for (SizeType i = 0; i < validatorCount; i++) - factory.DestroySchemaValidator(validators[i]); + for (SizeType i = 0; i < validatorCount; i++) { + if (validators[i]) { + factory.DestroySchemaValidator(validators[i]); + } + } factory.FreeState(validators); } if (patternPropertiesValidators) { - for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) - factory.DestroySchemaValidator(patternPropertiesValidators[i]); + for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) { + if (patternPropertiesValidators[i]) { + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + } + } factory.FreeState(patternPropertiesValidators); } if (patternPropertiesSchemas) @@ -397,6 +490,7 @@ struct SchemaValidationContext { SchemaValidatorFactoryType& factory; ErrorHandlerType& error_handler; const SchemaType* schema; + unsigned flags; const SchemaType* valueSchema; const Ch* invalidKeyword; ValidateErrorCode invalidCode; @@ -432,11 +526,14 @@ public: typedef Schema SchemaType; typedef GenericValue SValue; typedef IValidationErrorHandler ErrorHandler; + typedef GenericUri UriType; friend class GenericSchemaDocument; - Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : + Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator, const UriType& id = UriType()) : allocator_(allocator), uri_(schemaDocument->GetURI(), *allocator), + id_(id, allocator), + spec_(schemaDocument->GetSpecification()), pointer_(p, allocator), typeless_(schemaDocument->GetTypeless()), enum_(), @@ -469,14 +566,43 @@ public: maxLength_(~SizeType(0)), exclusiveMinimum_(false), exclusiveMaximum_(false), - defaultValueLength_(0) + defaultValueLength_(0), + readOnly_(false), + writeOnly_(false), + nullable_(false) { + GenericStringBuffer sb; + p.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Schema", sb.GetString(), id.GetString()); + typedef typename ValueType::ConstValueIterator ConstValueIterator; typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + // PR #1393 + // Early add this Schema and its $ref(s) in schemaDocument's map to avoid infinite + // recursion (with recursive schemas), since schemaDocument->getSchema() is always + // checked before creating a new one. Don't cache typeless_, though. + if (this != typeless_) { + typedef typename SchemaDocumentType::SchemaEntry SchemaEntry; + SchemaEntry *entry = schemaDocument->schemaMap_.template Push(); + new (entry) SchemaEntry(pointer_, this, true, allocator_); + schemaDocument->AddSchemaRefs(this); + } + if (!value.IsObject()) return; + // If we have an id property, resolve it with the in-scope id + // Not supported for open api 2.0 or 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (const ValueType* v = GetMember(value, GetIdString())) { + if (v->IsString()) { + UriType local(*v, allocator); + id_ = local.Resolve(id_, allocator); + RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), v->GetString(), id_.GetString()); + } + } + if (const ValueType* v = GetMember(value, GetTypeString())) { type_ = 0; if (v->IsString()) @@ -490,9 +616,9 @@ public: if (v->IsArray() && v->Size() > 0) { enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { - typedef Hasher > EnumHasherType; + typedef Hasher > EnumHasherType; char buffer[256u + 24]; - MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); + MemoryPoolAllocator hasherAllocator(buffer, sizeof(buffer)); EnumHasherType h(&hasherAllocator, 256); itr->Accept(h); enum_[enumCount_++] = h.GetHashCode(); @@ -500,16 +626,19 @@ public: } } - if (schemaDocument) { + if (schemaDocument) AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); + + // AnyOf, OneOf, Not not supported for open api 2.0 + if (schemaDocument && spec_.oapi != kVersion20) { AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); - } - if (const ValueType* v = GetMember(value, GetNotString())) { - schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document); - notValidatorIndex_ = validatorCount_; - validatorCount_++; + if (const ValueType* v = GetMember(value, GetNotString())) { + schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document, id_); + notValidatorIndex_ = validatorCount_; + validatorCount_++; + } } // Object @@ -524,12 +653,14 @@ public: if (properties && properties->IsObject()) for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) AddUniqueElement(allProperties, itr->name); - + if (required && required->IsArray()) for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) if (itr->IsString()) AddUniqueElement(allProperties, *itr); + // Dependencies not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) if (dependencies && dependencies->IsObject()) for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { AddUniqueElement(allProperties, itr->name); @@ -555,10 +686,12 @@ public: for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) { SizeType index; if (FindPropertyIndex(itr->name, &index)) - schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document); + schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document, id_); } } + // PatternProperties not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { PointerType q = p.Append(GetPatternPropertiesString(), allocator_); patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); @@ -566,8 +699,9 @@ public: for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { new (&patternProperties_[patternPropertyCount_]) PatternProperty(); - patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); - schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document); + PointerType r = q.Append(itr->name, allocator_); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name, schemaDocument, r); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, r, itr->value, document, id_); patternPropertyCount_++; } } @@ -582,6 +716,8 @@ public: } } + // Dependencies not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) if (dependencies && dependencies->IsObject()) { PointerType q = p.Append(GetDependenciesString(), allocator_); hasDependencies_ = true; @@ -599,7 +735,7 @@ public: } else if (itr->value.IsObject()) { hasSchemaDependencies_ = true; - schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document); + schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document, id_); properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; validatorCount_++; } @@ -611,7 +747,7 @@ public: if (v->IsBool()) additionalProperties_ = v->GetBool(); else if (v->IsObject()) - schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document); + schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document, id_); } AssignIfExist(minProperties_, value, GetMinPropertiesString()); @@ -621,23 +757,25 @@ public: if (const ValueType* v = GetMember(value, GetItemsString())) { PointerType q = p.Append(GetItemsString(), allocator_); if (v->IsObject()) // List validation - schemaDocument->CreateSchema(&itemsList_, q, *v, document); + schemaDocument->CreateSchema(&itemsList_, q, *v, document, id_); else if (v->IsArray()) { // Tuple validation itemsTuple_ = static_cast(allocator_->Malloc(sizeof(const Schema*) * v->Size())); SizeType index = 0; for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) - schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document); + schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document, id_); } } AssignIfExist(minItems_, value, GetMinItemsString()); AssignIfExist(maxItems_, value, GetMaxItemsString()); + // AdditionalItems not supported for openapi 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) { if (v->IsBool()) additionalItems_ = v->GetBool(); else if (v->IsObject()) - schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document); + schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document, id_); } AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); @@ -647,7 +785,7 @@ public: AssignIfExist(maxLength_, value, GetMaxLengthString()); if (const ValueType* v = GetMember(value, GetPatternString())) - pattern_ = CreatePattern(*v); + pattern_ = CreatePattern(*v, schemaDocument, p.Append(GetPatternString(), allocator_)); // Number if (const ValueType* v = GetMember(value, GetMinimumString())) @@ -670,6 +808,23 @@ public: if (v->IsString()) defaultValueLength_ = v->GetStringLength(); + // ReadOnly - open api only (until draft 7 supported) + // WriteOnly - open api 3 only (until draft 7 supported) + // Both can't be true + if (spec_.oapi != kVersionNone) + AssignIfExist(readOnly_, value, GetReadOnlyString()); + if (spec_.oapi >= kVersion30) + AssignIfExist(writeOnly_, value, GetWriteOnlyString()); + if (readOnly_ && writeOnly_) + schemaDocument->SchemaError(kSchemaErrorReadOnlyAndWriteOnly, p); + + // Nullable - open api 3 only + // If true add 'null' as allowable type + if (spec_.oapi >= kVersion30) { + AssignIfExist(nullable_, value, GetNullableString()); + if (nullable_) + AddType(GetNullString()); + } } ~Schema() { @@ -697,11 +852,20 @@ public: return uri_; } + const UriType& GetId() const { + return id_; + } + + const Specification& GetSpecification() const { + return spec_; + } + const PointerType& GetPointer() const { return pointer_; } bool BeginValue(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::BeginValue"); if (context.inArray) { if (uniqueItems_) context.valueUniqueness = true; @@ -733,6 +897,8 @@ public: } RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndValue"); + // Only check pattern properties if we have validators if (context.patternPropertiesValidatorCount > 0) { bool otherValid = false; SizeType count = context.patternPropertiesValidatorCount; @@ -775,87 +941,98 @@ public: foundEnum:; } - if (allOf_.schemas) - for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) - if (!context.validators[i]->IsValid()) { - context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count); - RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf); - } - - if (anyOf_.schemas) { - for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) - if (context.validators[i]->IsValid()) - goto foundAny; - context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count); - RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf); - foundAny:; - } + // Only check allOf etc if we have validators + if (context.validatorCount > 0) { + if (allOf_.schemas) + for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) + if (!context.validators[i]->IsValid()) { + context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf); + } - if (oneOf_.schemas) { - bool oneValid = false; - for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) - if (context.validators[i]->IsValid()) { - if (oneValid) { - context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true); - RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch); - } else - oneValid = true; - } - if (!oneValid) { - context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, false); - RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf); + if (anyOf_.schemas) { + for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) + if (context.validators[i]->IsValid()) + goto foundAny; + context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf); + foundAny:; } - } - if (not_ && context.validators[notValidatorIndex_]->IsValid()) { - context.error_handler.Disallowed(); - RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot); + if (oneOf_.schemas) { + bool oneValid = false; + SizeType firstMatch = 0; + for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if (context.validators[i]->IsValid()) { + if (oneValid) { + context.error_handler.MultipleOneOf(firstMatch, i - oneOf_.begin); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch); + } else { + oneValid = true; + firstMatch = i - oneOf_.begin; + } + } + if (!oneValid) { + context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf); + } + } + + if (not_ && context.validators[notValidatorIndex_]->IsValid()) { + context.error_handler.Disallowed(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot); + } } return true; } bool Null(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Null"); if (!(type_ & (1 << kNullSchemaType))) { DisallowedType(context, GetNullString()); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); } return CreateParallelValidator(context); } - - bool Bool(Context& context, bool) const { - if (!(type_ & (1 << kBooleanSchemaType))) { - DisallowedType(context, GetBooleanString()); - RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); - } + + bool Bool(Context& context, bool b) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Bool", b); + if (!CheckBool(context, b)) + return false; return CreateParallelValidator(context); } bool Int(Context& context, int i) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int", (int64_t)i); if (!CheckInt(context, i)) return false; return CreateParallelValidator(context); } bool Uint(Context& context, unsigned u) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint", (uint64_t)u); if (!CheckUint(context, u)) return false; return CreateParallelValidator(context); } bool Int64(Context& context, int64_t i) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int64", i); if (!CheckInt(context, i)) return false; return CreateParallelValidator(context); } bool Uint64(Context& context, uint64_t u) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint64", u); if (!CheckUint(context, u)) return false; return CreateParallelValidator(context); } bool Double(Context& context, double d) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Double", d); if (!(type_ & (1 << kNumberSchemaType))) { DisallowedType(context, GetNumberString()); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); @@ -866,14 +1043,15 @@ public: if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) return false; - + if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) return false; - + return CreateParallelValidator(context); } - + bool String(Context& context, const Ch* str, SizeType length, bool) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::String", str); if (!(type_ & (1 << kStringSchemaType))) { DisallowedType(context, GetStringString()); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); @@ -902,6 +1080,7 @@ public: } bool StartObject(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartObject"); if (!(type_ & (1 << kObjectSchemaType))) { DisallowedType(context, GetObjectString()); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); @@ -921,8 +1100,10 @@ public: return CreateParallelValidator(context); } - + bool Key(Context& context, const Ch* str, SizeType len, bool) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Key", str); + if (patternProperties_) { context.patternPropertiesSchemaCount = 0; for (SizeType i = 0; i < patternPropertyCount_; i++) @@ -949,7 +1130,7 @@ public: } if (additionalPropertiesSchema_) { - if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { + if (context.patternPropertiesSchemaCount > 0) { context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; context.valueSchema = typeless_; context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; @@ -974,6 +1155,7 @@ public: } bool EndObject(Context& context, SizeType memberCount) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndObject"); if (hasRequired_) { context.error_handler.StartMissingProperties(); for (SizeType index = 0; index < propertyCount_; index++) @@ -1014,13 +1196,14 @@ public: } } if (context.error_handler.EndDependencyErrors()) - RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorDependencies); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorDependencies); } return true; } bool StartArray(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartArray"); context.arrayElementIndex = 0; context.inArray = true; // Ensure we note that we are in an array @@ -1033,13 +1216,14 @@ public: } bool EndArray(Context& context, SizeType elementCount) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndArray"); context.inArray = false; - + if (elementCount < minItems_) { context.error_handler.TooFewItems(elementCount, minItems_); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinItems); } - + if (elementCount > maxItems_) { context.error_handler.TooManyItems(elementCount, maxItems_); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxItems); @@ -1081,6 +1265,9 @@ public: case kValidateErrorAnyOf: return GetAnyOfString(); case kValidateErrorNot: return GetNotString(); + case kValidateErrorReadOnly: return GetReadOnlyString(); + case kValidateErrorWriteOnly: return GetWriteOnlyString(); + default: return GetNullString(); } } @@ -1128,6 +1315,14 @@ public: RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm') RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't') + RAPIDJSON_STRING_(Schema, '$', 's', 'c', 'h', 'e', 'm', 'a') + RAPIDJSON_STRING_(Ref, '$', 'r', 'e', 'f') + RAPIDJSON_STRING_(Id, 'i', 'd') + RAPIDJSON_STRING_(Swagger, 's', 'w', 'a', 'g', 'g', 'e', 'r') + RAPIDJSON_STRING_(OpenApi, 'o', 'p', 'e', 'n', 'a', 'p', 'i') + RAPIDJSON_STRING_(ReadOnly, 'r', 'e', 'a', 'd', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(WriteOnly, 'w', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(Nullable, 'n', 'u', 'l', 'l', 'a', 'b', 'l', 'e') #undef RAPIDJSON_STRING_ @@ -1193,7 +1388,7 @@ private: out.schemas = static_cast(allocator_->Malloc(out.count * sizeof(const Schema*))); memset(out.schemas, 0, sizeof(Schema*)* out.count); for (SizeType i = 0; i < out.count; i++) - schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document); + schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document, id_); out.begin = validatorCount_; validatorCount_ += out.count; } @@ -1202,10 +1397,11 @@ private: #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX template - RegexType* CreatePattern(const ValueType& value) { + RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) { if (value.IsString()) { RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_); if (!r->IsValid()) { + sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength()); r->~RegexType(); AllocatorType::Free(r); r = 0; @@ -1221,13 +1417,14 @@ private: } #elif RAPIDJSON_SCHEMA_USE_STDREGEX template - RegexType* CreatePattern(const ValueType& value) { + RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) { if (value.IsString()) { RegexType *r = static_cast(allocator_->Malloc(sizeof(RegexType))); try { return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); } - catch (const std::regex_error&) { + catch (const std::regex_error& e) { + sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength()); AllocatorType::Free(r); } } @@ -1240,7 +1437,9 @@ private: } #else template - RegexType* CreatePattern(const ValueType&) { return 0; } + RegexType* CreatePattern(const ValueType&) { + return 0; + } static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } #endif // RAPIDJSON_SCHEMA_USE_STDREGEX @@ -1255,6 +1454,9 @@ private: else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); } + // Creates parallel validators for allOf, anyOf, oneOf, not and schema dependencies, if required. + // Also creates a hasher for enums and array uniqueness, if required. + // Also a useful place to add type-independent error checks. bool CreateParallelValidator(Context& context) const { if (enum_ || context.arrayUniqueness) context.hasher = context.factory.CreateHasher(); @@ -1262,6 +1464,7 @@ private: if (validatorCount_) { RAPIDJSON_ASSERT(context.validators == 0); context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); + std::memset(context.validators, 0, sizeof(ISchemaValidator*) * validatorCount_); context.validatorCount = validatorCount_; // Always return after first failure for these sub-validators @@ -1270,10 +1473,10 @@ private: if (anyOf_.schemas) CreateSchemaValidators(context, anyOf_, false); - + if (oneOf_.schemas) CreateSchemaValidators(context, oneOf_, false); - + if (not_) context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_, false); @@ -1284,6 +1487,16 @@ private: } } + // Add any other type-independent checks here + if (readOnly_ && (context.flags & kValidateWriteFlag)) { + context.error_handler.DisallowedWhenWriting(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorReadOnly); + } + if (writeOnly_ && (context.flags & kValidateReadFlag)) { + context.error_handler.DisallowedWhenReading(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorWriteOnly); + } + return true; } @@ -1297,7 +1510,7 @@ private: SizeType len = name.GetStringLength(); const Ch* str = name.GetString(); for (SizeType index = 0; index < propertyCount_; index++) - if (properties_[index].name.GetStringLength() == len && + if (properties_[index].name.GetStringLength() == len && (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) { *outIndex = index; @@ -1306,6 +1519,14 @@ private: return false; } + bool CheckBool(Context& context, bool) const { + if (!(type_ & (1 << kBooleanSchemaType))) { + DisallowedType(context, GetBooleanString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return true; + } + bool CheckInt(Context& context, int64_t i) const { if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { DisallowedType(context, GetIntegerString()); @@ -1420,9 +1641,13 @@ private: bool CheckDoubleMultipleOf(Context& context, double d) const { double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); - double q = std::floor(a / b); - double r = a - q * b; - if (r > 0.0) { + double q = a / b; + double qRounded = std::floor(q + 0.5); + double scaledEpsilon = (q + qRounded) * std::numeric_limits::epsilon(); + double difference = std::abs(qRounded - q); + bool isMultiple = (difference <= scaledEpsilon) + || (difference < std::numeric_limits::min()); + if (!isMultiple) { context.error_handler.NotMultipleOf(d, multipleOf_); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); } @@ -1458,7 +1683,7 @@ private: struct PatternProperty { PatternProperty() : schema(), pattern() {} - ~PatternProperty() { + ~PatternProperty() { if (pattern) { pattern->~RegexType(); AllocatorType::Free(pattern); @@ -1470,6 +1695,8 @@ private: AllocatorType* allocator_; SValue uri_; + UriType id_; + Specification spec_; PointerType pointer_; const SchemaType* typeless_; uint64_t* enum_; @@ -1512,8 +1739,12 @@ private: SValue multipleOf_; bool exclusiveMinimum_; bool exclusiveMaximum_; - + SizeType defaultValueLength_; + + bool readOnly_; + bool writeOnly_; + bool nullable_; }; template @@ -1555,9 +1786,18 @@ template class IGenericRemoteSchemaDocumentProvider { public: typedef typename SchemaDocumentType::Ch Ch; + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; virtual ~IGenericRemoteSchemaDocumentProvider() {} virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; + virtual const SchemaDocumentType* GetRemoteDocument(const GenericUri uri, Specification& spec) { + // Default implementation just calls through for compatibility + // Following line suppresses unused parameter warning + (void)spec; + // printf("GetRemoteDocument: %d %d\n", spec.draft, spec.oapi); + return GetRemoteDocument(uri.GetBaseString(), uri.GetBaseStringLength()); + } }; /////////////////////////////////////////////////////////////////////////////// @@ -1582,7 +1822,9 @@ public: typedef typename EncodingType::Ch Ch; typedef internal::Schema SchemaType; typedef GenericPointer PointerType; - typedef GenericValue URIType; + typedef GenericValue GValue; + typedef GenericUri UriType; + typedef GenericStringRef StringRefType; friend class internal::Schema; template friend class GenericSchemaValidator; @@ -1596,46 +1838,53 @@ public: \param uriLength Length of \c name, in code points. \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. \param allocator An optional allocator instance for allocating memory. Can be null. + \param pointer An optional JSON pointer to the start of the schema document + \param spec Optional schema draft or OpenAPI version. Used if no specification in document. Defaults to draft-04. */ explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0, - IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : + IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0, + const PointerType& pointer = PointerType(), // PR #1393 + const Specification& spec = Specification(kDraft04)) : remoteProvider_(remoteProvider), allocator_(allocator), ownAllocator_(), root_(), typeless_(), schemaMap_(allocator, kInitialSchemaMapSize), - schemaRef_(allocator, kInitialSchemaRefSize) + schemaRef_(allocator, kInitialSchemaRefSize), + spec_(spec), + error_(kObjectType), + currentError_() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::GenericSchemaDocument"); if (!allocator_) ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); Ch noUri[1] = {0}; uri_.SetString(uri ? uri : noUri, uriLength, *allocator_); + docId_ = UriType(uri_, allocator_); typeless_ = static_cast(allocator_->Malloc(sizeof(SchemaType))); - new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_); + new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_, docId_); + + // Establish the schema draft or open api version. + // We only ever look for '$schema' or 'swagger' or 'openapi' at the root of the document. + SetSchemaSpecification(document); // Generate root schema, it will call CreateSchema() to create sub-schemas, - // And call AddRefSchema() if there are $ref. - CreateSchemaRecursive(&root_, PointerType(), document, document); - - // Resolve $ref - while (!schemaRef_.Empty()) { - SchemaRefEntry* refEntry = schemaRef_.template Pop(1); - if (const SchemaType* s = GetSchema(refEntry->target)) { - if (refEntry->schema) - *refEntry->schema = s; - - // Create entry in map if not exist - if (!GetSchema(refEntry->source)) { - new (schemaMap_.template Push()) SchemaEntry(refEntry->source, const_cast(s), false, allocator_); - } - } - else if (refEntry->schema) - *refEntry->schema = typeless_; - - refEntry->~SchemaRefEntry(); + // And call HandleRefSchema() if there are $ref. + // PR #1393 use input pointer if supplied + root_ = typeless_; + if (pointer.GetTokenCount() == 0) { + CreateSchemaRecursive(&root_, pointer, document, document, docId_); + } + else if (const ValueType* v = pointer.Get(document)) { + CreateSchema(&root_, pointer, *v, document, docId_); + } + else { + GenericStringBuffer sb; + pointer.StringifyUriFragment(sb); + SchemaErrorValue(kSchemaErrorStartUnknown, PointerType(), sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch))); } RAPIDJSON_ASSERT(root_ != 0); @@ -1653,7 +1902,11 @@ public: typeless_(rhs.typeless_), schemaMap_(std::move(rhs.schemaMap_)), schemaRef_(std::move(rhs.schemaRef_)), - uri_(std::move(rhs.uri_)) + uri_(std::move(rhs.uri_)), + docId_(std::move(rhs.docId_)), + spec_(rhs.spec_), + error_(std::move(rhs.error_)), + currentError_(std::move(rhs.currentError_)) { rhs.remoteProvider_ = 0; rhs.allocator_ = 0; @@ -1672,26 +1925,87 @@ public: Allocator::Free(typeless_); } + // these may contain some allocator data so clear before deleting ownAllocator_ + uri_.SetNull(); + error_.SetNull(); + currentError_.SetNull(); + RAPIDJSON_DELETE(ownAllocator_); } - const URIType& GetURI() const { return uri_; } + const GValue& GetURI() const { return uri_; } + + const Specification& GetSpecification() const { return spec_; } + bool IsSupportedSpecification() const { return spec_.IsSupported(); } + + //! Static method to get the specification of any schema document + // Returns kDraftNone if document is silent + static const Specification GetSpecification(const ValueType& document) { + SchemaDraft draft = GetSchemaDraft(document); + if (draft != kDraftNone) + return Specification(draft); + else { + OpenApiVersion oapi = GetOpenApiVersion(document); + if (oapi != kVersionNone) + return Specification(oapi); + } + return Specification(kDraftNone); + } //! Get the root schema. const SchemaType& GetRoot() const { return *root_; } -private: + //! Gets the error object. + GValue& GetError() { return error_; } + const GValue& GetError() const { return error_; } + + static const StringRefType& GetSchemaErrorKeyword(SchemaErrorCode schemaErrorCode) { + switch (schemaErrorCode) { + case kSchemaErrorStartUnknown: return GetStartUnknownString(); + case kSchemaErrorRefPlainName: return GetRefPlainNameString(); + case kSchemaErrorRefInvalid: return GetRefInvalidString(); + case kSchemaErrorRefPointerInvalid: return GetRefPointerInvalidString(); + case kSchemaErrorRefUnknown: return GetRefUnknownString(); + case kSchemaErrorRefCyclical: return GetRefCyclicalString(); + case kSchemaErrorRefNoRemoteProvider: return GetRefNoRemoteProviderString(); + case kSchemaErrorRefNoRemoteSchema: return GetRefNoRemoteSchemaString(); + case kSchemaErrorRegexInvalid: return GetRegexInvalidString(); + case kSchemaErrorSpecUnknown: return GetSpecUnknownString(); + case kSchemaErrorSpecUnsupported: return GetSpecUnsupportedString(); + case kSchemaErrorSpecIllegal: return GetSpecIllegalString(); + case kSchemaErrorReadOnlyAndWriteOnly: return GetReadOnlyAndWriteOnlyString(); + default: return GetNullString(); + } + } + + //! Default error method + void SchemaError(const SchemaErrorCode code, const PointerType& location) { + currentError_ = GValue(kObjectType); + AddCurrentError(code, location); + } + + //! Method for error with single string value insert + void SchemaErrorValue(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length) { + currentError_ = GValue(kObjectType); + currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_); + AddCurrentError(code, location); + } + + //! Method for error with invalid pointer + void SchemaErrorPointer(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length, const PointerType& pointer) { + currentError_ = GValue(kObjectType); + currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_); + currentError_.AddMember(GetOffsetString(), static_cast(pointer.GetParseErrorOffset() / sizeof(Ch)), *allocator_); + AddCurrentError(code, location); + } + + private: //! Prohibit copying GenericSchemaDocument(const GenericSchemaDocument&); //! Prohibit assignment GenericSchemaDocument& operator=(const GenericSchemaDocument&); - struct SchemaRefEntry { - SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {} - PointerType source; - PointerType target; - const SchemaType** schema; - }; + typedef const PointerType* SchemaRefPtr; // PR #1393 struct SchemaEntry { SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} @@ -1706,79 +2020,361 @@ private: bool owned; }; - void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { - if (schema) - *schema = typeless_; + void AddErrorInstanceLocation(GValue& result, const PointerType& location) { + GenericStringBuffer sb; + location.StringifyUriFragment(sb); + GValue instanceRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), *allocator_); + result.AddMember(GetInstanceRefString(), instanceRef, *allocator_); + } + void AddError(GValue& keyword, GValue& error) { + typename GValue::MemberIterator member = error_.FindMember(keyword); + if (member == error_.MemberEnd()) + error_.AddMember(keyword, error, *allocator_); + else { + if (member->value.IsObject()) { + GValue errors(kArrayType); + errors.PushBack(member->value, *allocator_); + member->value = errors; + } + member->value.PushBack(error, *allocator_); + } + } + + void AddCurrentError(const SchemaErrorCode code, const PointerType& location) { + RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, GetSchemaErrorKeyword(code)); + currentError_.AddMember(GetErrorCodeString(), code, *allocator_); + AddErrorInstanceLocation(currentError_, location); + AddError(GValue(GetSchemaErrorKeyword(code)).Move(), currentError_); + } + +#define RAPIDJSON_STRING_(name, ...) \ + static const StringRefType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const StringRefType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1)); \ + return v;\ + } + + RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') + RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') + RAPIDJSON_STRING_(Value, 'v', 'a', 'l', 'u', 'e') + RAPIDJSON_STRING_(Offset, 'o', 'f', 'f', 's', 'e', 't') + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(SpecUnknown, 'S', 'p', 'e', 'c', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(SpecUnsupported, 'S', 'p', 'e', 'c', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd') + RAPIDJSON_STRING_(SpecIllegal, 'S', 'p', 'e', 'c', 'I', 'l', 'l', 'e', 'g', 'a', 'l') + RAPIDJSON_STRING_(StartUnknown, 'S', 't', 'a', 'r', 't', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(RefPlainName, 'R', 'e', 'f', 'P', 'l', 'a', 'i', 'n', 'N', 'a', 'm', 'e') + RAPIDJSON_STRING_(RefInvalid, 'R', 'e', 'f', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + RAPIDJSON_STRING_(RefPointerInvalid, 'R', 'e', 'f', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + RAPIDJSON_STRING_(RefUnknown, 'R', 'e', 'f', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(RefCyclical, 'R', 'e', 'f', 'C', 'y', 'c', 'l', 'i', 'c', 'a', 'l') + RAPIDJSON_STRING_(RefNoRemoteProvider, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r') + RAPIDJSON_STRING_(RefNoRemoteSchema, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'S', 'c', 'h', 'e', 'm', 'a') + RAPIDJSON_STRING_(ReadOnlyAndWriteOnly, 'R', 'e', 'a', 'd', 'O', 'n', 'l', 'y', 'A', 'n', 'd', 'W', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(RegexInvalid, 'R', 'e', 'g', 'e', 'x', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + +#undef RAPIDJSON_STRING_ + + // Static method to get schema draft of any schema document + static SchemaDraft GetSchemaDraft(const ValueType& document) { + static const Ch kDraft03String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '3', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft04String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '4', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft05String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '5', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft06String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '6', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft07String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '7', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft2019_09String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '1', '9', '-', '0', '9', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' }; + static const Ch kDraft2020_12String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '2', '0', '-', '1', '2', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' }; + + if (!document.IsObject()) { + return kDraftNone; + } + + // Get the schema draft from the $schema keyword at the supplied location + typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSchemaString()); + if (itr != document.MemberEnd()) { + if (!itr->value.IsString()) return kDraftUnknown; + const UriType draftUri(itr->value); + // Check base uri for match + if (draftUri.Match(UriType(kDraft04String), false)) return kDraft04; + if (draftUri.Match(UriType(kDraft05String), false)) return kDraft05; + if (draftUri.Match(UriType(kDraft06String), false)) return kDraft06; + if (draftUri.Match(UriType(kDraft07String), false)) return kDraft07; + if (draftUri.Match(UriType(kDraft03String), false)) return kDraft03; + if (draftUri.Match(UriType(kDraft2019_09String), false)) return kDraft2019_09; + if (draftUri.Match(UriType(kDraft2020_12String), false)) return kDraft2020_12; + return kDraftUnknown; + } + // $schema not found + return kDraftNone; + } + + + // Get open api version of any schema document + static OpenApiVersion GetOpenApiVersion(const ValueType& document) { + static const Ch kVersion20String[] = { '2', '.', '0', '\0' }; + static const Ch kVersion30String[] = { '3', '.', '0', '.', '\0' }; // ignore patch level + static const Ch kVersion31String[] = { '3', '.', '1', '.', '\0' }; // ignore patch level + static SizeType len = internal::StrLen(kVersion30String); + + if (!document.IsObject()) { + return kVersionNone; + } + + // Get the open api version from the swagger / openapi keyword at the supplied location + typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSwaggerString()); + if (itr == document.MemberEnd()) itr = document.FindMember(SchemaType::GetOpenApiString()); + if (itr != document.MemberEnd()) { + if (!itr->value.IsString()) return kVersionUnknown; + const ValueType kVersion20Value(kVersion20String); + if (kVersion20Value == itr->value) return kVersion20; // must match 2.0 exactly + const ValueType kVersion30Value(kVersion30String); + if (itr->value.GetStringLength() > len && kVersion30Value == ValueType(itr->value.GetString(), len)) return kVersion30; // must match 3.0.x + const ValueType kVersion31Value(kVersion31String); + if (itr->value.GetStringLength() > len && kVersion31Value == ValueType(itr->value.GetString(), len)) return kVersion31; // must match 3.1.x + return kVersionUnknown; + } + // swagger or openapi not found + return kVersionNone; + } + + // Get the draft of the schema or the open api version (which implies the draft). + // Report an error if schema draft or open api version not supported or not recognized, or both in document, and carry on. + void SetSchemaSpecification(const ValueType& document) { + // Look for '$schema', 'swagger' or 'openapi' keyword at document root + SchemaDraft docDraft = GetSchemaDraft(document); + OpenApiVersion docOapi = GetOpenApiVersion(document); + // Error if both in document + if (docDraft != kDraftNone && docOapi != kVersionNone) + SchemaError(kSchemaErrorSpecIllegal, PointerType()); + // Use document draft or open api version if present or use spec from constructor + if (docDraft != kDraftNone) + spec_ = Specification(docDraft); + else if (docOapi != kVersionNone) + spec_ = Specification(docOapi); + // Error if draft or version unknown + if (spec_.draft == kDraftUnknown || spec_.oapi == kVersionUnknown) + SchemaError(kSchemaErrorSpecUnknown, PointerType()); + else if (!spec_.IsSupported()) + SchemaError(kSchemaErrorSpecUnsupported, PointerType()); + } + + // Changed by PR #1393 + void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { if (v.GetType() == kObjectType) { - const SchemaType* s = GetSchema(pointer); - if (!s) - CreateSchema(schema, pointer, v, document); + UriType newid = UriType(CreateSchema(schema, pointer, v, document, id), allocator_); for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) - CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document); + CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid); } else if (v.GetType() == kArrayType) for (SizeType i = 0; i < v.Size(); i++) - CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document); + CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document, id); } - void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + // Changed by PR #1393 + const UriType& CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { RAPIDJSON_ASSERT(pointer.IsValid()); + GenericStringBuffer sb; + pointer.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::CreateSchema", sb.GetString(), id.GetString()); if (v.IsObject()) { - if (!HandleRefSchema(pointer, schema, v, document)) { - SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_); - new (schemaMap_.template Push()) SchemaEntry(pointer, s, true, allocator_); + if (const SchemaType* sc = GetSchema(pointer)) { + if (schema) + *schema = sc; + AddSchemaRefs(const_cast(sc)); + } + else if (!HandleRefSchema(pointer, schema, v, document, id)) { + // The new schema constructor adds itself and its $ref(s) to schemaMap_ + SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_, id); if (schema) *schema = s; + return s->GetId(); } } + else { + if (schema) + *schema = typeless_; + AddSchemaRefs(typeless_); + } + return id; } - bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) { - static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' }; - static const ValueType kRefValue(kRefString, 4); - - typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue); + // Changed by PR #1393 + // TODO should this return a UriType& ? + bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document, const UriType& id) { + typename ValueType::ConstMemberIterator itr = v.FindMember(SchemaType::GetRefString()); if (itr == v.MemberEnd()) return false; + GenericStringBuffer sb; + source.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::HandleRefSchema", sb.GetString(), id.GetString()); + // Resolve the source pointer to the $ref'ed schema (finally) + new (schemaRef_.template Push()) SchemaRefPtr(&source); + if (itr->value.IsString()) { SizeType len = itr->value.GetStringLength(); - if (len > 0) { - const Ch* s = itr->value.GetString(); - SizeType i = 0; - while (i < len && s[i] != '#') // Find the first # - i++; - - if (i > 0) { // Remote reference, resolve immediately - if (remoteProvider_) { - if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) { - PointerType pointer(&s[i], len - i, allocator_); - if (pointer.IsValid()) { - if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) { - if (schema) - *schema = sc; - new (schemaMap_.template Push()) SchemaEntry(source, const_cast(sc), false, allocator_); - return true; + if (len == 0) + SchemaError(kSchemaErrorRefInvalid, source); + else { + // First resolve $ref against the in-scope id + UriType scopeId = UriType(id, allocator_); + UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_); + RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), itr->value.GetString(), ref.GetString()); + // See if the resolved $ref minus the fragment matches a resolved id in this document + // Search from the root. Returns the subschema in the document and its absolute JSON pointer. + PointerType basePointer = PointerType(); + const ValueType *base = FindId(document, ref, basePointer, docId_, false); + if (!base) { + // Remote reference - call the remote document provider + if (!remoteProvider_) + SchemaError(kSchemaErrorRefNoRemoteProvider, source); + else { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref, spec_)) { + const Ch* s = ref.GetFragString(); + len = ref.GetFragStringLength(); + if (len <= 1 || s[1] == '/') { + // JSON pointer fragment, absolute in the remote schema + const PointerType pointer(s, len, allocator_); + if (!pointer.IsValid()) + SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, pointer); + else { + // Get the subschema + if (const SchemaType *sc = remoteDocument->GetSchema(pointer)) { + if (schema) + *schema = sc; + AddSchemaRefs(const_cast(sc)); + return true; + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); } - } - } + } else + // Plain name fragment, not allowed in remote schema + SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len); + } else + SchemaErrorValue(kSchemaErrorRefNoRemoteSchema, source, ref.GetString(), ref.GetStringLength()); } } - else if (s[i] == '#') { // Local reference, defer resolution - PointerType pointer(&s[i], len - i, allocator_); - if (pointer.IsValid()) { - if (const ValueType* nv = pointer.Get(document)) - if (HandleRefSchema(source, schema, *nv, document)) + else { // Local reference + const Ch* s = ref.GetFragString(); + len = ref.GetFragStringLength(); + if (len <= 1 || s[1] == '/') { + // JSON pointer fragment, relative to the resolved URI + const PointerType relPointer(s, len, allocator_); + if (!relPointer.IsValid()) + SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, relPointer); + else { + // Get the subschema + if (const ValueType *pv = relPointer.Get(*base)) { + // Now get the absolute JSON pointer by adding relative to base + PointerType pointer(basePointer, allocator_); + for (SizeType i = 0; i < relPointer.GetTokenCount(); i++) + pointer = pointer.Append(relPointer.GetTokens()[i], allocator_); + if (IsCyclicRef(pointer)) + SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength()); + else { + // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there + // TODO: cache pointer <-> id mapping + size_t unresolvedTokenIndex; + scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_); + CreateSchema(schema, pointer, *pv, document, scopeId); + return true; + } + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } + } else { + // Plain name fragment, relative to the resolved URI + // Not supported in open api 2.0 and 3.0 + PointerType pointer(allocator_); + if (spec_.oapi == kVersion20 || spec_.oapi == kVersion30) + SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len); + // See if the fragment matches an id in this document. + // Search from the base we just established. Returns the subschema in the document and its absolute JSON pointer. + else if (const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_), true, basePointer)) { + if (IsCyclicRef(pointer)) + SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength()); + else { + // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there + // TODO: cache pointer <-> id mapping + size_t unresolvedTokenIndex; + scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_); + CreateSchema(schema, pointer, *pv, document, scopeId); return true; - - new (schemaRef_.template Push()) SchemaRefEntry(source, pointer, schema, allocator_); - return true; + } + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); } } } } + + // Invalid/Unknown $ref + if (schema) + *schema = typeless_; + AddSchemaRefs(typeless_); + return true; + } + + //! Find the first subschema with a resolved 'id' that matches the specified URI. + // If full specified use all URI else ignore fragment. + // If found, return a pointer to the subschema and its JSON pointer. + // TODO cache pointer <-> id mapping + ValueType* FindId(const ValueType& doc, const UriType& finduri, PointerType& resptr, const UriType& baseuri, bool full, const PointerType& here = PointerType()) const { + SizeType i = 0; + ValueType* resval = 0; + UriType tempuri = UriType(finduri, allocator_); + UriType localuri = UriType(baseuri, allocator_); + if (doc.GetType() == kObjectType) { + // Establish the base URI of this object + typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString()); + if (m != doc.MemberEnd() && m->value.GetType() == kStringType) { + localuri = UriType(m->value, allocator_).Resolve(baseuri, allocator_); + } + // See if it matches + if (localuri.Match(finduri, full)) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::FindId (match)", full ? localuri.GetString() : localuri.GetBaseString()); + resval = const_cast(&doc); + resptr = here; + return resval; + } + // No match, continue looking + for (m = doc.MemberBegin(); m != doc.MemberEnd(); ++m) { + if (m->value.GetType() == kObjectType || m->value.GetType() == kArrayType) { + resval = FindId(m->value, finduri, resptr, localuri, full, here.Append(m->name.GetString(), m->name.GetStringLength(), allocator_)); + } + if (resval) break; + } + } else if (doc.GetType() == kArrayType) { + // Continue looking + for (typename ValueType::ConstValueIterator v = doc.Begin(); v != doc.End(); ++v) { + if (v->GetType() == kObjectType || v->GetType() == kArrayType) { + resval = FindId(*v, finduri, resptr, localuri, full, here.Append(i, allocator_)); + } + if (resval) break; + i++; + } + } + return resval; + } + + // Added by PR #1393 + void AddSchemaRefs(SchemaType* schema) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::AddSchemaRefs"); + while (!schemaRef_.Empty()) { + SchemaRefPtr *ref = schemaRef_.template Pop(1); + SchemaEntry *entry = schemaMap_.template Push(); + new (entry) SchemaEntry(**ref, schema, false, allocator_); + } + } + + // Added by PR #1393 + bool IsCyclicRef(const PointerType& pointer) const { + for (const SchemaRefPtr* ref = schemaRef_.template Bottom(); ref != schemaRef_.template End(); ++ref) + if (pointer == **ref) + return true; return false; } @@ -1807,8 +2403,12 @@ private: const SchemaType* root_; //!< Root schema. SchemaType* typeless_; internal::Stack schemaMap_; // Stores created Pointer -> Schemas - internal::Stack schemaRef_; // Stores Pointer from $ref and schema which holds the $ref - URIType uri_; + internal::Stack schemaRef_; // Stores Pointer(s) from $ref(s) until resolved + GValue uri_; // Schema document URI + UriType docId_; + Specification spec_; + GValue error_; + GValue currentError_; }; //! GenericSchemaDocument using Value type. @@ -1872,11 +2472,10 @@ public: currentError_(), missingDependents_(), valid_(true), - flags_(kValidateDefaultFlags) -#if RAPIDJSON_SCHEMA_VERBOSE - , depth_(0) -#endif + flags_(kValidateDefaultFlags), + depth_(0) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator"); } //! Constructor with output handler. @@ -1904,11 +2503,10 @@ public: currentError_(), missingDependents_(), valid_(true), - flags_(kValidateDefaultFlags) -#if RAPIDJSON_SCHEMA_VERBOSE - , depth_(0) -#endif + flags_(kValidateDefaultFlags), + depth_(0) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (output handler)"); } //! Destructor. @@ -1941,13 +2539,12 @@ public: return flags_; } - //! Checks whether the current state is valid. - // Implementation of ISchemaValidator virtual bool IsValid() const { if (!valid_) return false; if (GetContinueOnErrors() && !error_.ObjectEmpty()) return false; return true; } + //! End of Implementation of ISchemaValidator //! Gets the error object. ValueType& GetError() { return error_; } @@ -1963,7 +2560,7 @@ public: // If reporting all errors, the stack will be empty, so return "errors". const Ch* GetInvalidSchemaKeyword() const { if (!schemaStack_.Empty()) return CurrentContext().invalidKeyword; - if (GetContinueOnErrors() && !error_.ObjectEmpty()) return (const Ch*)GetErrorsString(); + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return static_cast(GetErrorsString()); return 0; } @@ -2155,13 +2752,29 @@ public: void NoneOf(ISchemaValidator** subvalidators, SizeType count) { AddErrorArray(kValidateErrorAnyOf, subvalidators, count); } - void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched = false) { - AddErrorArray(matched ? kValidateErrorOneOfMatch : kValidateErrorOneOf, subvalidators, count); + void NotOneOf(ISchemaValidator** subvalidators, SizeType count) { + AddErrorArray(kValidateErrorOneOf, subvalidators, count); + } + void MultipleOneOf(SizeType index1, SizeType index2) { + ValueType matches(kArrayType); + matches.PushBack(index1, GetStateAllocator()); + matches.PushBack(index2, GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetMatchesString(), matches, GetStateAllocator()); + AddCurrentError(kValidateErrorOneOfMatch); } void Disallowed() { currentError_.SetObject(); AddCurrentError(kValidateErrorNot); } + void DisallowedWhenWriting() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorReadOnly); + } + void DisallowedWhenReading() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorWriteOnly); + } #define RAPIDJSON_STRING_(name, ...) \ static const StringRefType& Get##name##String() {\ @@ -2180,25 +2793,18 @@ public: RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') RAPIDJSON_STRING_(ErrorMessage, 'e', 'r', 'r', 'o', 'r', 'M', 'e', 's', 's', 'a', 'g', 'e') RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's') + RAPIDJSON_STRING_(Matches, 'm', 'a', 't', 'c', 'h', 'e', 's') #undef RAPIDJSON_STRING_ -#if RAPIDJSON_SCHEMA_VERBOSE -#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ -RAPIDJSON_MULTILINEMACRO_BEGIN\ - *documentStack_.template Push() = '\0';\ - documentStack_.template Pop(1);\ - internal::PrintInvalidDocument(documentStack_.template Bottom());\ -RAPIDJSON_MULTILINEMACRO_END -#else -#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() -#endif - #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ if (!valid_) return false; \ if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\ - RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ - return valid_ = false;\ + *documentStack_.template Push() = '\0';\ + documentStack_.template Pop(1);\ + RAPIDJSON_SCHEMA_PRINT(InvalidDocument, documentStack_.template Bottom());\ + valid_ = false;\ + return valid_;\ } #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ @@ -2235,52 +2841,68 @@ RAPIDJSON_MULTILINEMACRO_END { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } bool StartObject() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartObject"); RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); - return valid_ = !outputHandler_ || outputHandler_->StartObject(); + valid_ = !outputHandler_ || outputHandler_->StartObject(); + return valid_; } bool Key(const Ch* str, SizeType len, bool copy) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::Key", str); if (!valid_) return false; AppendToken(str, len); - if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) return valid_ = false; + if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); - return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy); + valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy); + return valid_; } bool EndObject(SizeType memberCount) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndObject"); if (!valid_) return false; RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); - if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) return valid_ = false; + if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); } bool StartArray() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartArray"); RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); - return valid_ = !outputHandler_ || outputHandler_->StartArray(); + valid_ = !outputHandler_ || outputHandler_->StartArray(); + return valid_; } bool EndArray(SizeType elementCount) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndArray"); if (!valid_) return false; RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); - if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) return valid_ = false; + if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); } -#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ #undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ #undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ // Implementation of ISchemaStateFactory virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root, const bool inheritContinueOnErrors) { + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); ISchemaValidator* sv = new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom(), documentStack_.GetSize(), -#if RAPIDJSON_SCHEMA_VERBOSE depth_ + 1, -#endif &GetStateAllocator()); - sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(unsigned)kValidateContinueOnErrorFlag); + sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~static_cast(kValidateContinueOnErrorFlag)); return sv; } @@ -2311,6 +2933,7 @@ RAPIDJSON_MULTILINEMACRO_END virtual void FreeState(void* p) { StateAllocator::Free(p); } + // End of implementation of ISchemaStateFactory private: typedef typename SchemaType::Context Context; @@ -2321,9 +2944,7 @@ private: const SchemaDocumentType& schemaDocument, const SchemaType& root, const char* basePath, size_t basePathSize, -#if RAPIDJSON_SCHEMA_VERBOSE unsigned depth, -#endif StateAllocator* allocator = 0, size_t schemaStackCapacity = kDefaultSchemaStackCapacity, size_t documentStackCapacity = kDefaultDocumentStackCapacity) @@ -2339,11 +2960,10 @@ private: currentError_(), missingDependents_(), valid_(true), - flags_(kValidateDefaultFlags) -#if RAPIDJSON_SCHEMA_VERBOSE - , depth_(depth) -#endif + flags_(kValidateDefaultFlags), + depth_(depth) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (internal)", basePath && basePathSize ? basePath : ""); if (basePath && basePathSize) memcpy(documentStack_.template Push(basePathSize), basePath, basePathSize); } @@ -2359,6 +2979,7 @@ private: } bool BeginValue() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::BeginValue"); if (schemaStack_.Empty()) PushSchema(root_); else { @@ -2380,6 +3001,7 @@ private: ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); + std::memset(va, 0, sizeof(ISchemaValidator*) * count); for (SizeType i = 0; i < count; i++) va[validatorCount++] = CreateSchemaValidator(*sa[i], true); // Inherit continueOnError } @@ -2390,17 +3012,15 @@ private: } bool EndValue() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndValue"); if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors()) return false; -#if RAPIDJSON_SCHEMA_VERBOSE GenericStringBuffer sb; - schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); - + schemaDocument_->GetPointer(&CurrentSchema()).StringifyUriFragment(sb); *documentStack_.template Push() = '\0'; documentStack_.template Pop(1); - internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom()); -#endif + RAPIDJSON_SCHEMA_PRINT(ValidatorPointers, sb.GetString(), documentStack_.template Bottom(), depth_); void* hasher = CurrentContext().hasher; uint64_t h = hasher && CurrentContext().arrayUniqueness ? static_cast(hasher)->GetHashCode() : 0; @@ -2451,7 +3071,7 @@ private: } } - RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, *this, &schema); } + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, *this, &schema, flags_); } RAPIDJSON_FORCEINLINE void PopSchema() { Context* c = schemaStack_.template Pop(1); @@ -2553,9 +3173,7 @@ private: ValueType missingDependents_; bool valid_; unsigned flags_; -#if RAPIDJSON_SCHEMA_VERBOSE unsigned depth_; -#endif }; typedef GenericSchemaValidator SchemaValidator; diff --git a/contrib/rapidjson/include/rapidjson/uri.h b/contrib/rapidjson/include/rapidjson/uri.h new file mode 100644 index 000000000..f93e508a4 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/uri.h @@ -0,0 +1,481 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// (C) Copyright IBM Corporation 2021 +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_URI_H_ +#define RAPIDJSON_URI_H_ + +#include "internal/strfunc.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// GenericUri + +template +class GenericUri { +public: + typedef typename ValueType::Ch Ch; +#if RAPIDJSON_HAS_STDSTRING + typedef std::basic_string String; +#endif + + //! Constructors + GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + } + + GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri, len); + } + + GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri, internal::StrLen(uri)); + } + + // Use with specializations of GenericValue + template GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + const Ch* u = uri.template Get(); // TypeHelper from document.h + Parse(u, internal::StrLen(u)); + } + +#if RAPIDJSON_HAS_STDSTRING + GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri.c_str(), internal::StrLen(uri.c_str())); + } +#endif + + //! Copy constructor + GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() { + *this = rhs; + } + + //! Copy constructor + GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + *this = rhs; + } + + //! Destructor. + ~GenericUri() { + Free(); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator + GenericUri& operator=(const GenericUri& rhs) { + if (this != &rhs) { + // Do not delete ownAllocator + Free(); + Allocate(rhs.GetStringLength()); + auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength()); + path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength()); + query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength()); + frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength()); + base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength()); + uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength()); + CopyPart(uri_, rhs.uri_, rhs.GetStringLength()); + } + return *this; + } + + //! Getters + // Use with specializations of GenericValue + template void Get(T& uri, Allocator& allocator) { + uri.template Set(this->GetString(), allocator); // TypeHelper from document.h + } + + const Ch* GetString() const { return uri_; } + SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen(uri_); } + const Ch* GetBaseString() const { return base_; } + SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen(base_); } + const Ch* GetSchemeString() const { return scheme_; } + SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen(scheme_); } + const Ch* GetAuthString() const { return auth_; } + SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen(auth_); } + const Ch* GetPathString() const { return path_; } + SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen(path_); } + const Ch* GetQueryString() const { return query_; } + SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen(query_); } + const Ch* GetFragString() const { return frag_; } + SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen(frag_); } + +#if RAPIDJSON_HAS_STDSTRING + static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); } + static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); } + static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); } + static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); } + static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); } + static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); } + static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); } +#endif + + //! Equality operators + bool operator==(const GenericUri& rhs) const { + return Match(rhs, true); + } + + bool operator!=(const GenericUri& rhs) const { + return !Match(rhs, true); + } + + bool Match(const GenericUri& uri, bool full = true) const { + Ch* s1; + Ch* s2; + if (full) { + s1 = uri_; + s2 = uri.uri_; + } else { + s1 = base_; + s2 = uri.base_; + } + if (s1 == s2) return true; + if (s1 == 0 || s2 == 0) return false; + return internal::StrCmp(s1, s2) == 0; + } + + //! Resolve this URI against another (base) URI in accordance with URI resolution rules. + // See https://tools.ietf.org/html/rfc3986 + // Use for resolving an id or $ref with an in-scope id. + // Returns a new GenericUri for the resolved URI. + GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) { + GenericUri resuri; + resuri.allocator_ = allocator; + // Ensure enough space for combining paths + resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash + + if (!(GetSchemeStringLength() == 0)) { + // Use all of this URI + resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength()); + resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + resuri.RemoveDotSegments(); + } else { + // Use the base scheme + resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength()); + if (!(GetAuthStringLength() == 0)) { + // Use this auth, path, query + resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + resuri.RemoveDotSegments(); + } else { + // Use the base auth + resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength()); + if (GetPathStringLength() == 0) { + // Use the base path + resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength()); + if (GetQueryStringLength() == 0) { + // Use the base query + resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength()); + } else { + // Use this query + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + } + } else { + if (path_[0] == '/') { + // Absolute path - use all of this path + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.RemoveDotSegments(); + } else { + // Relative path - append this path to base path after base path's last slash + size_t pos = 0; + if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) { + resuri.path_[pos] = '/'; + pos++; + } + size_t lastslashpos = baseuri.GetPathStringLength(); + while (lastslashpos > 0) { + if (baseuri.path_[lastslashpos - 1] == '/') break; + lastslashpos--; + } + std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch)); + pos += lastslashpos; + resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength()); + resuri.RemoveDotSegments(); + } + // Use this query + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + } + } + } + // Always use this frag + resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength()); + + // Re-constitute base_ and uri_ + resuri.SetBase(); + resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1; + resuri.SetUri(); + return resuri; + } + + //! Get the allocator of this GenericUri. + Allocator& GetAllocator() { return *allocator_; } + +private: + // Allocate memory for a URI + // Returns total amount allocated + std::size_t Allocate(std::size_t len) { + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated. + // Order: scheme, auth, path, query, frag, base, uri + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + size_t total = (3 * len + 7) * sizeof(Ch); + scheme_ = static_cast(allocator_->Malloc(total)); + *scheme_ = '\0'; + auth_ = scheme_; + auth_++; + *auth_ = '\0'; + path_ = auth_; + path_++; + *path_ = '\0'; + query_ = path_; + query_++; + *query_ = '\0'; + frag_ = query_; + frag_++; + *frag_ = '\0'; + base_ = frag_; + base_++; + *base_ = '\0'; + uri_ = base_; + uri_++; + *uri_ = '\0'; + return total; + } + + // Free memory for a URI + void Free() { + if (scheme_) { + Allocator::Free(scheme_); + scheme_ = 0; + } + } + + // Parse a URI into constituent scheme, authority, path, query, & fragment parts + // Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per + // https://tools.ietf.org/html/rfc3986 + void Parse(const Ch* uri, std::size_t len) { + std::size_t start = 0, pos1 = 0, pos2 = 0; + Allocate(len); + + // Look for scheme ([^:/?#]+):)? + if (start < len) { + while (pos1 < len) { + if (uri[pos1] == ':') break; + pos1++; + } + if (pos1 != len) { + while (pos2 < len) { + if (uri[pos2] == '/') break; + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + if (pos1 < pos2) { + pos1++; + std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch)); + scheme_[pos1] = '\0'; + start = pos1; + } + } + } + // Look for auth (//([^/?#]*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + auth_ = scheme_ + GetSchemeStringLength(); + auth_++; + *auth_ = '\0'; + if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') { + pos2 = start + 2; + while (pos2 < len) { + if (uri[pos2] == '/') break; + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch)); + auth_[pos2 - start] = '\0'; + start = pos2; + } + // Look for path ([^?#]*) + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + path_ = auth_ + GetAuthStringLength(); + path_++; + *path_ = '\0'; + if (start < len) { + pos2 = start; + while (pos2 < len) { + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + if (start != pos2) { + std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch)); + path_[pos2 - start] = '\0'; + if (path_[0] == '/') + RemoveDotSegments(); // absolute path - normalize + start = pos2; + } + } + // Look for query (\?([^#]*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + query_ = path_ + GetPathStringLength(); + query_++; + *query_ = '\0'; + if (start < len && uri[start] == '?') { + pos2 = start + 1; + while (pos2 < len) { + if (uri[pos2] == '#') break; + pos2++; + } + if (start != pos2) { + std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch)); + query_[pos2 - start] = '\0'; + start = pos2; + } + } + // Look for fragment (#(.*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + frag_ = query_ + GetQueryStringLength(); + frag_++; + *frag_ = '\0'; + if (start < len && uri[start] == '#') { + std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch)); + frag_[len - start] = '\0'; + } + + // Re-constitute base_ and uri_ + base_ = frag_ + GetFragStringLength() + 1; + SetBase(); + uri_ = base_ + GetBaseStringLength() + 1; + SetUri(); + } + + // Reconstitute base + void SetBase() { + Ch* next = base_; + std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch)); + next+= GetSchemeStringLength(); + std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch)); + next+= GetAuthStringLength(); + std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch)); + next+= GetPathStringLength(); + std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch)); + next+= GetQueryStringLength(); + *next = '\0'; + } + + // Reconstitute uri + void SetUri() { + Ch* next = uri_; + std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch)); + next+= GetBaseStringLength(); + std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch)); + next+= GetFragStringLength(); + *next = '\0'; + } + + // Copy a part from one GenericUri to another + // Return the pointer to the next part to be copied to + Ch* CopyPart(Ch* to, Ch* from, std::size_t len) { + RAPIDJSON_ASSERT(to != 0); + RAPIDJSON_ASSERT(from != 0); + std::memcpy(to, from, len * sizeof(Ch)); + to[len] = '\0'; + Ch* next = to + len + 1; + return next; + } + + // Remove . and .. segments from the path_ member. + // https://tools.ietf.org/html/rfc3986 + // This is done in place as we are only removing segments. + void RemoveDotSegments() { + std::size_t pathlen = GetPathStringLength(); + std::size_t pathpos = 0; // Position in path_ + std::size_t newpos = 0; // Position in new path_ + + // Loop through each segment in original path_ + while (pathpos < pathlen) { + // Get next segment, bounded by '/' or end + size_t slashpos = 0; + while ((pathpos + slashpos) < pathlen) { + if (path_[pathpos + slashpos] == '/') break; + slashpos++; + } + // Check for .. and . segments + if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') { + // Backup a .. segment in the new path_ + // We expect to find a previously added slash at the end or nothing + RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/'); + size_t lastslashpos = newpos; + // Make sure we don't go beyond the start segment + if (lastslashpos > 1) { + // Find the next to last slash and back up to it + lastslashpos--; + while (lastslashpos > 0) { + if (path_[lastslashpos - 1] == '/') break; + lastslashpos--; + } + // Set the new path_ position + newpos = lastslashpos; + } + } else if (slashpos == 1 && path_[pathpos] == '.') { + // Discard . segment, leaves new path_ unchanged + } else { + // Move any other kind of segment to the new path_ + RAPIDJSON_ASSERT(newpos <= pathpos); + std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch)); + newpos += slashpos; + // Add slash if not at end + if ((pathpos + slashpos) < pathlen) { + path_[newpos] = '/'; + newpos++; + } + } + // Move to next segment + pathpos += slashpos + 1; + } + path_[newpos] = '\0'; + } + + Ch* uri_; // Everything + Ch* base_; // Everything except fragment + Ch* scheme_; // Includes the : + Ch* auth_; // Includes the // + Ch* path_; // Absolute if starts with / + Ch* query_; // Includes the ? + Ch* frag_; // Includes the # + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Uri. +}; + +//! GenericUri for Value (UTF-8, default allocator). +typedef GenericUri Uri; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_URI_H_ diff --git a/contrib/rapidjson/include/rapidjson/writer.h b/contrib/rapidjson/include/rapidjson/writer.h index 8b389219a..632e02ce7 100644 --- a/contrib/rapidjson/include/rapidjson/writer.h +++ b/contrib/rapidjson/include/rapidjson/writer.h @@ -67,6 +67,7 @@ enum WriteFlag { kWriteNoFlags = 0, //!< No flags are set. kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteNanAndInfNullFlag = 4, //!< Allow writing of Infinity, -Infinity and NaN as null. kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS }; @@ -348,8 +349,13 @@ protected: bool WriteDouble(double d) { if (internal::Double(d).IsNanOrInf()) { - if (!(writeFlags & kWriteNanAndInfFlag)) + if (!(writeFlags & kWriteNanAndInfFlag) && !(writeFlags & kWriteNanAndInfNullFlag)) return false; + if (writeFlags & kWriteNanAndInfNullFlag) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); + return true; + } if (internal::Double(d).IsNan()) { PutReserve(*os_, 3); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); @@ -548,6 +554,11 @@ inline bool Writer::WriteDouble(double d) { // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) return false; + if (kWriteDefaultFlags & kWriteNanAndInfNullFlag) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); + return true; + } if (internal::Double(d).IsNan()) { PutReserve(*os_, 3); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); diff --git a/contrib/rapidjson/readme.md b/contrib/rapidjson/readme.md index b833a98e8..ac683b051 100644 --- a/contrib/rapidjson/readme.md +++ b/contrib/rapidjson/readme.md @@ -6,7 +6,7 @@ Tencent is pleased to support the open source community by making RapidJSON available. -Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. * [RapidJSON GitHub](https://github.com/Tencent/rapidjson/) * RapidJSON Documentation @@ -43,7 +43,7 @@ RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml]( More features can be read [here](doc/features.md). -JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in fully compliance with RFC7159/ECMA-404, with optional support of relaxed syntax. More information about JSON can be obtained at +JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in full compliance with RFC7159/ECMA-404, with optional support of relaxed syntax. More information about JSON can be obtained at * [Introducing JSON](http://json.org/) * [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159) * [Standard ECMA-404: The JSON Data Interchange Format](https://www.ecma-international.org/publications/standards/Ecma-404.htm) @@ -72,6 +72,9 @@ Users can build and run the unit tests on their platform/compiler. RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path. +Alternatively, if you are using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager you can download and install rapidjson with CMake integration in a single command: +* vcpkg install rapidjson + RapidJSON uses following software as its dependencies: * [CMake](https://cmake.org/) as a general build tool * (optional) [Doxygen](http://www.doxygen.org) to build documentation @@ -158,3 +161,50 @@ More [examples](https://github.com/Tencent/rapidjson/tree/master/example) are av * [parsebyparts](https://github.com/Tencent/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): Implements an `AsyncDocumentParser` which can parse JSON in parts, using C++11 thread. * [filterkey](https://github.com/Tencent/rapidjson/blob/master/example/filterkey/filterkey.cpp): A command line tool to remove all values with user-specified key. * [filterkeydom](https://github.com/Tencent/rapidjson/blob/master/example/filterkeydom/filterkeydom.cpp): Same tool as above, but it demonstrates how to use a generator to populate a `Document`. + +## Contributing + +RapidJSON welcomes contributions. When contributing, please follow the code below. + +### Issues + +Feel free to submit issues and enhancement requests. + +Please help us by providing **minimal reproducible examples**, because source code is easier to let other people understand what happens. +For crash problems on certain platforms, please bring stack dump content with the detail of the OS, compiler, etc. + +Please try breakpoint debugging first, tell us what you found, see if we can start exploring based on more information been prepared. + +### Workflow + +In general, we follow the "fork-and-pull" Git workflow. + + 1. **Fork** the repo on GitHub + 2. **Clone** the project to your own machine + 3. **Checkout** a new branch on your fork, start developing on the branch + 4. **Test** the change before commit, Make sure the changes pass all the tests, including `unittest` and `preftest`, please add test case for each new feature or bug-fix if needed. + 5. **Commit** changes to your own branch + 6. **Push** your work back up to your fork + 7. Submit a **Pull request** so that we can review your changes + +NOTE: Be sure to merge the latest from "upstream" before making a pull request! + +### Copyright and Licensing + +You can copy and paste the license summary from below. + +``` +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + +Licensed under the MIT License (the "License"); you may not use this file except +in compliance with the License. You may obtain a copy of the License at + +http://opensource.org/licenses/MIT + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +``` diff --git a/contrib/stb/stb_image.h b/contrib/stb/stb_image.h index 5e807a0a6..a632d5435 100644 --- a/contrib/stb/stb_image.h +++ b/contrib/stb/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb +/* stb_image - v2.29 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: @@ -48,6 +48,7 @@ LICENSE RECENT REVISION HISTORY: + 2.29 (2023-05-xx) optimizations 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.26 (2020-07-13) many minor fixes @@ -1072,8 +1073,8 @@ static int stbi__addints_valid(int a, int b) return a <= INT_MAX - b; } -// returns 1 if the product of two signed shorts is valid, 0 on overflow. -static int stbi__mul2shorts_valid(short a, short b) +// returns 1 if the product of two ints fits in a signed short, 0 on overflow. +static int stbi__mul2shorts_valid(int a, int b) { if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid @@ -3384,13 +3385,13 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) return 1; } -static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) { // some JPEGs have junk at end, skip over it but if we find what looks // like a valid marker, resume there while (!stbi__at_eof(j->s)) { - int x = stbi__get8(j->s); - while (x == 255) { // might be a marker + stbi_uc x = stbi__get8(j->s); + while (x == 0xff) { // might be a marker if (stbi__at_eof(j->s)) return STBI__MARKER_none; x = stbi__get8(j->s); if (x != 0x00 && x != 0xff) { @@ -4176,6 +4177,7 @@ typedef struct { stbi_uc *zbuffer, *zbuffer_end; int num_bits; + int hit_zeof_once; stbi__uint32 code_buffer; char *zout; @@ -4242,9 +4244,20 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) int b,s; if (a->num_bits < 16) { if (stbi__zeof(a)) { - return -1; /* report error for unexpected end of data. */ + if (!a->hit_zeof_once) { + // This is the first time we hit eof, insert 16 extra padding btis + // to allow us to keep going; if we actually consume any of them + // though, that is invalid data. This is caught later. + a->hit_zeof_once = 1; + a->num_bits += 16; // add 16 implicit zero bits + } else { + // We already inserted our extra 16 padding bits and are again + // out, this stream is actually prematurely terminated. + return -1; + } + } else { + stbi__fill_bits(a); } - stbi__fill_bits(a); } b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; if (b) { @@ -4309,6 +4322,13 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) int len,dist; if (z == 256) { a->zout = zout; + if (a->hit_zeof_once && a->num_bits < 16) { + // The first time we hit zeof, we inserted 16 extra zero bits into our bit + // buffer so the decoder can just do its speculative decoding. But if we + // actually consumed any of those bits (which is the case when num_bits < 16), + // the stream actually read past the end so it is malformed. + return stbi__err("unexpected end","Corrupt PNG"); + } return 1; } if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data @@ -4320,7 +4340,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); - if (zout + len > a->zout_end) { + if (len > a->zout_end - zout) { if (!stbi__zexpand(a, zout, len)) return 0; zout = a->zout; } @@ -4464,6 +4484,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) if (!stbi__parse_zlib_header(a)) return 0; a->num_bits = 0; a->code_buffer = 0; + a->hit_zeof_once = 0; do { final = stbi__zreceive(a,1); type = stbi__zreceive(a,2); @@ -4619,9 +4640,8 @@ enum { STBI__F_up=2, STBI__F_avg=3, STBI__F_paeth=4, - // synthetic filters used for first scanline to avoid needing a dummy row of 0s - STBI__F_avg_first, - STBI__F_paeth_first + // synthetic filter used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first }; static stbi_uc first_row_filter[5] = @@ -4630,29 +4650,56 @@ static stbi_uc first_row_filter[5] = STBI__F_sub, STBI__F_none, STBI__F_avg_first, - STBI__F_paeth_first + STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub }; static int stbi__paeth(int a, int b, int c) { - int p = a + b - c; - int pa = abs(p-a); - int pb = abs(p-b); - int pc = abs(p-c); - if (pa <= pb && pa <= pc) return a; - if (pb <= pc) return b; - return c; + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; } static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; +// adds an extra all-255 alpha channel +// dest == src is legal +// img_n must be 1 or 3 +static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) +{ + int i; + // must process data backwards since we allow dest==src + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + dest[i*2+1] = 255; + dest[i*2+0] = src[i]; + } + } else { + STBI_ASSERT(img_n == 3); + for (i=x-1; i >= 0; --i) { + dest[i*4+3] = 255; + dest[i*4+2] = src[i*3+2]; + dest[i*4+1] = src[i*3+1]; + dest[i*4+0] = src[i*3+0]; + } + } +} + // create the png data from post-deflated data static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) { - int bytes = (depth == 16? 2 : 1); + int bytes = (depth == 16 ? 2 : 1); stbi__context *s = a->s; stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 img_len, img_width_bytes; + stbi_uc *filter_buf; + int all_ok = 1; int k; int img_n = s->img_n; // copy it into a local for later @@ -4664,8 +4711,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); + // note: error exits here don't need to clean up a->out individually, + // stbi__do_png always does on error. if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); + if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); img_len = (img_width_bytes + 1) * y; // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, @@ -4673,189 +4723,137 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r // so just check for raw_len < img_len always. if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + // Allocate two scan lines worth of filter workspace buffer. + filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); + if (!filter_buf) return stbi__err("outofmem", "Out of memory"); + + // Filtering for low-bit-depth images + if (depth < 8) { + filter_bytes = 1; + width = img_width_bytes; + } + for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *prior; + // cur/prior filter buffers alternate + stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; + stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; + stbi_uc *dest = a->out + stride*j; + int nk = width * filter_bytes; int filter = *raw++; - if (filter > 4) - return stbi__err("invalid filter","Corrupt PNG"); - - if (depth < 8) { - if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG"); - cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place - filter_bytes = 1; - width = img_width_bytes; + // check filter type + if (filter > 4) { + all_ok = stbi__err("invalid filter","Corrupt PNG"); + break; } - prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; - // handle first byte explicitly - for (k=0; k < filter_bytes; ++k) { - switch (filter) { - case STBI__F_none : cur[k] = raw[k]; break; - case STBI__F_sub : cur[k] = raw[k]; break; - case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; - case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; - case STBI__F_avg_first : cur[k] = raw[k]; break; - case STBI__F_paeth_first: cur[k] = raw[k]; break; - } + // perform actual filtering + switch (filter) { + case STBI__F_none: + memcpy(cur, raw, nk); + break; + case STBI__F_sub: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); + break; + case STBI__F_up: + for (k = 0; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); + break; + case STBI__F_avg: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); + break; + case STBI__F_paeth: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); + break; + case STBI__F_avg_first: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); + break; } - if (depth == 8) { - if (img_n != out_n) - cur[img_n] = 255; // first pixel - raw += img_n; - cur += out_n; - prior += out_n; - } else if (depth == 16) { - if (img_n != out_n) { - cur[filter_bytes] = 255; // first pixel top byte - cur[filter_bytes+1] = 255; // first pixel bottom byte - } - raw += filter_bytes; - cur += output_bytes; - prior += output_bytes; - } else { - raw += 1; - cur += 1; - prior += 1; - } + raw += nk; - // this is a little gross, so that we don't switch per-pixel or per-component - if (depth < 8 || img_n == out_n) { - int nk = (width - 1)*filter_bytes; - #define STBI__CASE(f) \ - case f: \ - for (k=0; k < nk; ++k) - switch (filter) { - // "none" filter turns into a memcpy here; make that explicit. - case STBI__F_none: memcpy(cur, raw, nk); break; - STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; - STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; - STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; - STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; - STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; - STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; - } - #undef STBI__CASE - raw += nk; - } else { - STBI_ASSERT(img_n+1 == out_n); - #define STBI__CASE(f) \ - case f: \ - for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ - for (k=0; k < filter_bytes; ++k) - switch (filter) { - STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; - STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; - STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; - STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; - STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; - STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; - STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; - } - #undef STBI__CASE - - // the loop above sets the high byte of the pixels' alpha, but for - // 16 bit png files we also need the low byte set. we'll do that here. - if (depth == 16) { - cur = a->out + stride*j; // start at the beginning of the row again - for (i=0; i < x; ++i,cur+=output_bytes) { - cur[filter_bytes+1] = 255; - } - } - } - } - - // we make a separate pass to expand bits to pixels; for performance, - // this could run two scanlines behind the above code, so it won't - // intefere with filtering but will still be in the cache. - if (depth < 8) { - for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; - // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit - // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + // expand decoded bits in cur to dest, also adding an extra alpha channel if desired + if (depth < 8) { stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + stbi_uc *in = cur; + stbi_uc *out = dest; + stbi_uc inb = 0; + stbi__uint32 nsmp = x*img_n; - // note that the final byte might overshoot and write more data than desired. - // we can allocate enough data that this never writes out of memory, but it - // could also overwrite the next scanline. can it overwrite non-empty data - // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. - // so we need to explicitly clamp the final ones - + // expand bits to bytes first if (depth == 4) { - for (k=x*img_n; k >= 2; k-=2, ++in) { - *cur++ = scale * ((*in >> 4) ); - *cur++ = scale * ((*in ) & 0x0f); + for (i=0; i < nsmp; ++i) { + if ((i & 1) == 0) inb = *in++; + *out++ = scale * (inb >> 4); + inb <<= 4; } - if (k > 0) *cur++ = scale * ((*in >> 4) ); } else if (depth == 2) { - for (k=x*img_n; k >= 4; k-=4, ++in) { - *cur++ = scale * ((*in >> 6) ); - *cur++ = scale * ((*in >> 4) & 0x03); - *cur++ = scale * ((*in >> 2) & 0x03); - *cur++ = scale * ((*in ) & 0x03); + for (i=0; i < nsmp; ++i) { + if ((i & 3) == 0) inb = *in++; + *out++ = scale * (inb >> 6); + inb <<= 2; } - if (k > 0) *cur++ = scale * ((*in >> 6) ); - if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); - if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); - } else if (depth == 1) { - for (k=x*img_n; k >= 8; k-=8, ++in) { - *cur++ = scale * ((*in >> 7) ); - *cur++ = scale * ((*in >> 6) & 0x01); - *cur++ = scale * ((*in >> 5) & 0x01); - *cur++ = scale * ((*in >> 4) & 0x01); - *cur++ = scale * ((*in >> 3) & 0x01); - *cur++ = scale * ((*in >> 2) & 0x01); - *cur++ = scale * ((*in >> 1) & 0x01); - *cur++ = scale * ((*in ) & 0x01); + } else { + STBI_ASSERT(depth == 1); + for (i=0; i < nsmp; ++i) { + if ((i & 7) == 0) inb = *in++; + *out++ = scale * (inb >> 7); + inb <<= 1; } - if (k > 0) *cur++ = scale * ((*in >> 7) ); - if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); - if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); - if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); - if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); - if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); - if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); } - if (img_n != out_n) { - int q; - // insert alpha = 255 - cur = a->out + stride*j; + + // insert alpha=255 values if desired + if (img_n != out_n) + stbi__create_png_alpha_expand8(dest, dest, x, img_n); + } else if (depth == 8) { + if (img_n == out_n) + memcpy(dest, cur, x*img_n); + else + stbi__create_png_alpha_expand8(dest, cur, x, img_n); + } else if (depth == 16) { + // convert the image data from big-endian to platform-native + stbi__uint16 *dest16 = (stbi__uint16*)dest; + stbi__uint32 nsmp = x*img_n; + + if (img_n == out_n) { + for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) + *dest16 = (cur[0] << 8) | cur[1]; + } else { + STBI_ASSERT(img_n+1 == out_n); if (img_n == 1) { - for (q=x-1; q >= 0; --q) { - cur[q*2+1] = 255; - cur[q*2+0] = cur[q]; + for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = 0xffff; } } else { STBI_ASSERT(img_n == 3); - for (q=x-1; q >= 0; --q) { - cur[q*4+3] = 255; - cur[q*4+2] = cur[q*3+2]; - cur[q*4+1] = cur[q*3+1]; - cur[q*4+0] = cur[q*3+0]; + for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = (cur[2] << 8) | cur[3]; + dest16[2] = (cur[4] << 8) | cur[5]; + dest16[3] = 0xffff; } } } } - } else if (depth == 16) { - // force the image data from big-endian to platform-native. - // this is done in a separate pass due to the decoding relying - // on the data being untouched, but could probably be done - // per-line during decode if care is taken. - stbi_uc *cur = a->out; - stbi__uint16 *cur16 = (stbi__uint16*)cur; - - for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { - *cur16 = (cur[0] << 8) | cur[1]; - } } + STBI_FREE(filter_buf); + if (!all_ok) return 0; + return 1; } diff --git a/contrib/unzip/crypt.h b/contrib/unzip/crypt.h index 1cc41f19d..f4b93b78d 100644 --- a/contrib/unzip/crypt.h +++ b/contrib/unzip/crypt.h @@ -32,8 +32,7 @@ /*********************************************************************** * Return the next byte in the pseudo-random sequence */ -static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) -{ +static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) { unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem * with any known compiler so far, though */ @@ -46,8 +45,7 @@ static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) /*********************************************************************** * Update the encryption keys with the next byte of plain text */ -static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) -{ +static int update_keys(unsigned long* pkeys, const z_crc_t* pcrc_32_tab, int c) { (*(pkeys+0)) = CRC32((*(pkeys+0)), c); (*(pkeys+1)) += (*(pkeys+0)) & 0xff; (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; @@ -63,8 +61,7 @@ static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) * Initialize the encryption keys and the random header according to * the given password. */ -static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) -{ +static void init_keys(const char* passwd, unsigned long* pkeys, const z_crc_t* pcrc_32_tab) { *(pkeys+0) = 305419896L; *(pkeys+1) = 591751049L; *(pkeys+2) = 878082192L; @@ -93,8 +90,7 @@ static unsigned crypthead(const char* passwd, /* password string */ int bufSize, unsigned long* pkeys, const z_crc_t* pcrc_32_tab, - unsigned long crcForCrypting) -{ + unsigned long crcForCrypting) { unsigned n; /* index in random header */ int t; /* temporary */ int c; /* random byte */ diff --git a/contrib/unzip/ioapi.c b/contrib/unzip/ioapi.c index 0ca29db6a..782d32469 100644 --- a/contrib/unzip/ioapi.c +++ b/contrib/unzip/ioapi.c @@ -14,7 +14,7 @@ #define _CRT_SECURE_NO_WARNINGS #endif -#if defined(__APPLE__) || defined(IOAPI_NO_64) +#if defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) @@ -28,8 +28,7 @@ #include "ioapi.h" -voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) -{ +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc, const void*filename, int mode) { if (pfilefunc->zfile_func64.zopen64_file != NULL) return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); else @@ -38,8 +37,7 @@ voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename } } -long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) -{ +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); else @@ -52,8 +50,7 @@ long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZP } } -ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) -{ +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc, voidpf filestream) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); else @@ -66,11 +63,9 @@ ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream } } -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) -{ +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32, const zlib_filefunc_def* p_filefunc32) { p_filefunc64_32->zfile_func64.zopen64_file = NULL; p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; p_filefunc64_32->zfile_func64.ztell64_file = NULL; @@ -84,16 +79,7 @@ void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filef -static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); -static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); -static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); -static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); -static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); - -static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) -{ +static voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; (void)opaque; @@ -111,8 +97,7 @@ static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, in return file; } -static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) -{ +static voidpf ZCALLBACK fopen64_file_func(voidpf opaque, const void* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; (void)opaque; @@ -131,24 +116,21 @@ static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, } -static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) -{ +static uLong ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uLong size) { uLong ret; (void)opaque; ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); return ret; } -static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) -{ +static uLong ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) { uLong ret; (void)opaque; ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); return ret; } -static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) -{ +static long ZCALLBACK ftell_file_func(voidpf opaque, voidpf stream) { long ret; (void)opaque; ret = ftell((FILE *)stream); @@ -156,16 +138,14 @@ static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) } -static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) -{ +static ZPOS64_T ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream) { ZPOS64_T ret; (void)opaque; ret = (ZPOS64_T)FTELLO_FUNC((FILE *)stream); return ret; } -static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) -{ +static long ZCALLBACK fseek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) { int fseek_origin=0; long ret; (void)opaque; @@ -188,8 +168,7 @@ static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offs return ret; } -static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) -{ +static long ZCALLBACK fseek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { int fseek_origin=0; long ret; (void)opaque; @@ -208,31 +187,28 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T } ret = 0; - if(FSEEKO_FUNC((FILE *)stream, (z_off_t)offset, fseek_origin) != 0) + if(FSEEKO_FUNC((FILE *)stream, (z_off64_t)offset, fseek_origin) != 0) ret = -1; return ret; } -static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) -{ +static int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream) { int ret; (void)opaque; ret = fclose((FILE *)stream); return ret; } -static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) -{ +static int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream) { int ret; (void)opaque; ret = ferror((FILE *)stream); return ret; } -void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def) -{ +void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen_file = fopen_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; @@ -243,8 +219,7 @@ void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def) pzlib_filefunc_def->opaque = NULL; } -void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = fopen64_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; diff --git a/contrib/unzip/ioapi.h b/contrib/unzip/ioapi.h index 548dafb5e..a2d2e6e60 100644 --- a/contrib/unzip/ioapi.h +++ b/contrib/unzip/ioapi.h @@ -50,7 +50,7 @@ #define ftello64 ftell #define fseeko64 fseek #else -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) #define fopen64 fopen #define ftello64 ftello #define fseeko64 fseeko @@ -82,7 +82,7 @@ #include "mz64conf.h" #endif -/* a type choosen by DEFINE */ +/* a type chosen by DEFINE */ #ifdef HAVE_64BIT_INT_CUSTOM typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; #else @@ -134,17 +134,17 @@ extern "C" { -typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); -typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); -typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); +typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode); +typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size); +typedef uLong (ZCALLBACK *write_file_func) (voidpf opaque, voidpf stream, const void* buf, uLong size); +typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream); +typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream); -typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream); +typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin); -/* here is the "old" 32 bits structure structure */ +/* here is the "old" 32 bits structure */ typedef struct zlib_filefunc_def_s { open_file_func zopen_file; @@ -157,9 +157,9 @@ typedef struct zlib_filefunc_def_s voidpf opaque; } zlib_filefunc_def; -typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) (voidpf opaque, voidpf stream); +typedef long (ZCALLBACK *seek64_file_func) (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin); +typedef voidpf (ZCALLBACK *open64_file_func) (voidpf opaque, const void* filename, int mode); typedef struct zlib_filefunc64_def_s { @@ -173,8 +173,8 @@ typedef struct zlib_filefunc64_def_s voidpf opaque; } zlib_filefunc64_def; -void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def); +void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def); /* now internal definition, only for zip.c and unzip.h */ typedef struct zlib_filefunc64_32_def_s @@ -193,11 +193,11 @@ typedef struct zlib_filefunc64_32_def_s #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) -voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); -long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); -ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); +voidpf call_zopen64(const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode); +long call_zseek64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin); +ZPOS64_T call_ztell64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream); -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index e703549d2..ea05b7d62 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -49,12 +49,12 @@ Copyright (C) 2007-2008 Even Rouault - Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G should only read the compressed/uncompressed size from the Zip64 format if the size from normal header was 0xFFFFFFFF - Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant - Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Oct-2009 - Mathias Svensson - Applied some bug fixes from patches received from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression method BZIP2 (bzip2 lib is required) Patch created by Daniel Borca Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer @@ -77,8 +77,6 @@ #ifdef STDC # include -# include -# include #endif #ifdef NO_ERRNO_H extern int errno; @@ -111,9 +109,6 @@ #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif -#ifndef TRYFREE -# define TRYFREE(p) { free(p);} -#endif #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) @@ -122,7 +117,7 @@ const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; -/* unz_file_info_interntal contain internal info about a file in zipfile*/ +/* unz_file_info64_internal contain internal info about a file in zipfile*/ typedef struct unz_file_info64_internal_s { ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ @@ -153,7 +148,7 @@ typedef struct ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ uLong compression_method; /* compression method (0==store) */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ int raw; @@ -166,7 +161,7 @@ typedef struct { zlib_filefunc64_32_def z_filefunc; int is64bitOpenFunction; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ unz_global_info64 gi; /* public global information */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ ZPOS64_T num_file; /* number of the current file in the zipfile*/ @@ -197,29 +192,44 @@ typedef struct #include "crypt.h" #endif + /* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been successfully opened for reading. + Reads a long in LSB order from the given gz_stream. Sets */ - -local int unz64local_getByte OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) -{ - unsigned char c; - int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) +local int unz64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) { + unsigned char c[2]; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,2); + if (err==2) { - *pi = (int)c; + *pX = c[0] | ((uLong)c[1] << 8); return UNZ_OK; } else { + *pX = 0; + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + +local int unz64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) { + unsigned char c[4]; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,4); + if (err==4) + { + *pX = c[0] | ((uLong)c[1] << 8) | ((uLong)c[2] << 16) | ((uLong)c[3] << 24); + return UNZ_OK; + } + else + { + *pX = 0; if (ZERROR64(*pzlib_filefunc_def,filestream)) return UNZ_ERRNO; else @@ -228,126 +238,29 @@ local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, v } -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unz64local_getShort OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; +local int unz64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) { + unsigned char c[8]; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,8); + if (err==8) + { + *pX = c[0] | ((ZPOS64_T)c[1] << 8) | ((ZPOS64_T)c[2] << 16) | ((ZPOS64_T)c[3] << 24) + | ((ZPOS64_T)c[4] << 32) | ((ZPOS64_T)c[5] << 40) | ((ZPOS64_T)c[6] << 48) | ((ZPOS64_T)c[7] << 56); + return UNZ_OK; + } else + { *pX = 0; - return err; -} - -local int unz64local_getLong OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX)); - - -local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX) -{ - ZPOS64_T x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<24; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<32; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<40; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<48; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<56; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } } /* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) -{ +local int strcmpcasenosensitive_internal(const char* fileName1, const char* fileName2) { for (;;) { char c1=*(fileName1++); @@ -379,19 +292,17 @@ local int strcmpcasenosensitive_internal (const char* fileName1, const char* fil #endif /* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + Compare two filenames (fileName1,fileName2). + If iCaseSensitivity = 1, comparison is case sensitive (like strcmp) + If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + If iCaseSensitivity = 0, case sensitivity is default of your operating system (like 1 on Unix, 2 on Windows) */ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, - const char* fileName2, - int iCaseSensitivity) - -{ + const char* fileName2, + int iCaseSensitivity) { if (iCaseSensitivity==0) iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; @@ -405,21 +316,23 @@ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, #define BUFREADCOMMENT (0x400) #endif +#ifndef CENTRALDIRINVALID +#define CENTRALDIRINVALID ((ZPOS64_T)(-1)) +#endif + /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); -local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; + ZPOS64_T uPosFound=CENTRALDIRINVALID; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; + return CENTRALDIRINVALID; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); @@ -429,7 +342,7 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) - return 0; + return CENTRALDIRINVALID; uBackRead = 4; while (uBackReadz_filefunc, s->filestream); - TRYFREE(s); + free(s); return UNZ_OK; } @@ -825,8 +727,7 @@ extern int ZEXPORT unzClose (unzFile file) Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) -{ +extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64* pglobal_info) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; @@ -835,8 +736,7 @@ extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_ return UNZ_OK; } -extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) -{ +extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; @@ -847,10 +747,9 @@ extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info return UNZ_OK; } /* - Translate date/time from Dos format to tm_unz (readable more easilty) + Translate date/time from Dos format to tm_unz (readable more easily) */ -local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) -{ +local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz* ptm) { ZPOS64_T uDate; uDate = (ZPOS64_T)(ulDosDate>>16); ptm->tm_mday = (int)(uDate&0x1f) ; @@ -865,28 +764,16 @@ local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) /* Get Info about the current file in the zipfile, with internal only info */ -local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unz64local_GetCurrentFileInfoInternal (unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) -{ +local int unz64local_GetCurrentFileInfoInternal(unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) { unz64_s* s; unz_file_info64 file_info; unz_file_info64_internal file_info_internal; @@ -1038,33 +925,31 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file, /* ZIP64 extra fields */ if (headerId == 0x0001) { - uLong uL1; + if(file_info.uncompressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } - if(file_info.uncompressed_size == MAXU32) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } + if(file_info.compressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } - if(file_info.compressed_size == MAXU32) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } + if(file_info_internal.offset_curfile == MAXU32) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } - if(file_info_internal.offset_curfile == MAXU32) - { - /* Relative Header offset */ - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info.disk_num_start == MAXU32) - { - /* Disk Start Number */ - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL1) != UNZ_OK) - err=UNZ_ERRNO; - } + if(file_info.disk_num_start == 0xffff) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + } } else @@ -1121,24 +1006,22 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file, No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, - unz_file_info64 * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ +extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) { return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); } -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, - unz_file_info * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ +extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) { int err; unz_file_info64 file_info64; err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, @@ -1162,7 +1045,7 @@ extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, pfile_info->internal_fa = file_info64.internal_fa; pfile_info->external_fa = file_info64.external_fa; - pfile_info->tmu_date = file_info64.tmu_date, + pfile_info->tmu_date = file_info64.tmu_date; pfile_info->compressed_size = (uLong)file_info64.compressed_size; @@ -1175,8 +1058,7 @@ extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ -extern int ZEXPORT unzGoToFirstFile (unzFile file) -{ +extern int ZEXPORT unzGoToFirstFile(unzFile file) { int err=UNZ_OK; unz64_s* s; if (file==NULL) @@ -1196,8 +1078,7 @@ extern int ZEXPORT unzGoToFirstFile (unzFile file) return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ -extern int ZEXPORT unzGoToNextFile (unzFile file) -{ +extern int ZEXPORT unzGoToNextFile(unzFile file) { unz64_s* s; int err; @@ -1229,8 +1110,7 @@ extern int ZEXPORT unzGoToNextFile (unzFile file) UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ -extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) -{ +extern int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) { unz64_s* s; int err; @@ -1305,8 +1185,7 @@ typedef struct unz_file_pos_s } unz_file_pos; */ -extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) -{ +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) { unz64_s* s; if (file==NULL || file_pos==NULL) @@ -1321,10 +1200,7 @@ extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) return UNZ_OK; } -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos) -{ +extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos* file_pos) { unz64_file_pos file_pos64; int err = unzGetFilePos64(file,&file_pos64); if (err==UNZ_OK) @@ -1335,8 +1211,7 @@ extern int ZEXPORT unzGetFilePos( return err; } -extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) -{ +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) { unz64_s* s; int err; @@ -1357,10 +1232,7 @@ extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos return err; } -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos) -{ +extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos* file_pos) { unz64_file_pos file_pos64; if (file_pos == NULL) return UNZ_PARAMERROR; @@ -1382,10 +1254,9 @@ extern int ZEXPORT unzGoToFilePos( store in *piSizeVar the size of extra info in local header (filename and size of extra field data) */ -local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, - ZPOS64_T * poffset_local_extrafield, - uInt * psize_local_extrafield) -{ +local int unz64local_CheckCurrentFileCoherencyHeader(unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) { uLong uMagic,uData,uFlags; uLong size_filename; uLong size_extra_field; @@ -1469,9 +1340,8 @@ local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVa Open for reading data the current file in the zipfile. If there is no error and the file is opened, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, - int* level, int raw, const char* password) -{ +extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int* method, + int* level, int raw, const char* password) { int err=UNZ_OK; uInt iSizeVar; unz64_s* s; @@ -1509,7 +1379,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, if (pfile_in_zip_read_info->read_buffer==NULL) { - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info); return UNZ_INTERNALERROR; } @@ -1566,8 +1436,8 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; else { - TRYFREE(pfile_in_zip_read_info->read_buffer); - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info->read_buffer); + free(pfile_in_zip_read_info); return err; } #else @@ -1587,8 +1457,8 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; else { - TRYFREE(pfile_in_zip_read_info->read_buffer); - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info->read_buffer); + free(pfile_in_zip_read_info); return err; } /* windowBits is passed < 0 to tell that there is no zlib header. @@ -1640,25 +1510,21 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, return UNZ_OK; } -extern int ZEXPORT unzOpenCurrentFile (unzFile file) -{ +extern int ZEXPORT unzOpenCurrentFile(unzFile file) { return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); } -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) -{ +extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char* password) { return unzOpenCurrentFile3(file, NULL, NULL, 0, password); } -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) -{ +extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int* method, int* level, int raw) { return unzOpenCurrentFile3(file, method, level, raw, NULL); } /** Addition for GDAL : START */ -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) -{ +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; s=(unz64_s*)file; @@ -1678,13 +1544,12 @@ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) buf contain buffer where data must be copied len the size of buf. - return the number of byte copied if somes bytes are copied + return the number of byte copied if some bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ -extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) -{ +extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { int err=UNZ_OK; uInt iRead = 0; unz64_s* s; @@ -1891,8 +1756,7 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) /* Give the current position in uncompressed data */ -extern z_off_t ZEXPORT unztell (unzFile file) -{ +extern z_off_t ZEXPORT unztell(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) @@ -1906,8 +1770,7 @@ extern z_off_t ZEXPORT unztell (unzFile file) return (z_off_t)pfile_in_zip_read_info->stream.total_out; } -extern ZPOS64_T ZEXPORT unztell64 (unzFile file) -{ +extern ZPOS64_T ZEXPORT unztell64(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; @@ -1926,8 +1789,7 @@ extern ZPOS64_T ZEXPORT unztell64 (unzFile file) /* return 1 if the end of file was reached, 0 elsewhere */ -extern int ZEXPORT unzeof (unzFile file) -{ +extern int ZEXPORT unzeof(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) @@ -1958,8 +1820,7 @@ more info in the local-header version than in the central-header) the return value is the number of bytes copied in buf, or (if <0) the error code */ -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) -{ +extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; uInt read_now; @@ -2006,8 +1867,7 @@ extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ -extern int ZEXPORT unzCloseCurrentFile (unzFile file) -{ +extern int ZEXPORT unzCloseCurrentFile(unzFile file) { int err=UNZ_OK; unz64_s* s; @@ -2029,7 +1889,7 @@ extern int ZEXPORT unzCloseCurrentFile (unzFile file) } - TRYFREE(pfile_in_zip_read_info->read_buffer); + free(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) inflateEnd(&pfile_in_zip_read_info->stream); @@ -2040,7 +1900,7 @@ extern int ZEXPORT unzCloseCurrentFile (unzFile file) pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info); s->pfile_in_zip_read=NULL; @@ -2053,8 +1913,7 @@ extern int ZEXPORT unzCloseCurrentFile (unzFile file) uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ -extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) -{ +extern int ZEXPORT unzGetGlobalComment(unzFile file, char * szComment, uLong uSizeBuf) { unz64_s* s; uLong uReadThis ; if (file==NULL) @@ -2081,8 +1940,7 @@ extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uS } /* Additions by RX '2004 */ -extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) -{ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) { unz64_s* s; if (file==NULL) @@ -2096,8 +1954,7 @@ extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) return s->pos_in_central_dir; } -extern uLong ZEXPORT unzGetOffset (unzFile file) -{ +extern uLong ZEXPORT unzGetOffset(unzFile file) { ZPOS64_T offset64; if (file==NULL) @@ -2106,8 +1963,7 @@ extern uLong ZEXPORT unzGetOffset (unzFile file) return (uLong)offset64; } -extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) -{ +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) { unz64_s* s; int err; @@ -2124,7 +1980,6 @@ extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) return err; } -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) -{ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) { return unzSetOffset64(file,pos); } diff --git a/contrib/unzip/unzip.h b/contrib/unzip/unzip.h index 6f95e94d7..5cfc9c627 100644 --- a/contrib/unzip/unzip.h +++ b/contrib/unzip/unzip.h @@ -150,21 +150,21 @@ typedef struct unz_file_info_s tm_unz tmu_date; } unz_file_info; -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); +extern int ZEXPORT unzStringFileNameCompare(const char* fileName1, + const char* fileName2, + int iCaseSensitivity); /* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + Compare two filenames (fileName1,fileName2). + If iCaseSensitivity = 1, comparison is case sensitive (like strcmp) + If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + If iCaseSensitivity = 0, case sensitivity is default of your operating system (like 1 on Unix, 2 on Windows) */ -extern unzFile ZEXPORT unzOpen OF((const char *path)); -extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +extern unzFile ZEXPORT unzOpen(const char *path); +extern unzFile ZEXPORT unzOpen64(const void *path); /* Open a Zip file. path contain the full pathname (by example, on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer @@ -181,41 +181,41 @@ extern unzFile ZEXPORT unzOpen64 OF((const void *path)); */ -extern unzFile ZEXPORT unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); +extern unzFile ZEXPORT unzOpen2(const char *path, + zlib_filefunc_def* pzlib_filefunc_def); /* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ -extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, - zlib_filefunc64_def* pzlib_filefunc_def)); +extern unzFile ZEXPORT unzOpen2_64(const void *path, + zlib_filefunc64_def* pzlib_filefunc_def); /* Open a Zip file, like unz64Open, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ -extern int ZEXPORT unzClose OF((unzFile file)); +extern int ZEXPORT unzClose(unzFile file); /* Close a ZipFile opened with unzOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzCloseCurrentFile before call unzClose. return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); +extern int ZEXPORT unzGetGlobalInfo(unzFile file, + unz_global_info *pglobal_info); -extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, - unz_global_info64 *pglobal_info)); +extern int ZEXPORT unzGetGlobalInfo64(unzFile file, + unz_global_info64 *pglobal_info); /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); +extern int ZEXPORT unzGetGlobalComment(unzFile file, + char *szComment, + uLong uSizeBuf); /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. @@ -226,22 +226,22 @@ extern int ZEXPORT unzGetGlobalComment OF((unzFile file, /***************************************************************************/ /* Unzip package allow you browse the directory of the zipfile */ -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +extern int ZEXPORT unzGoToFirstFile(unzFile file); /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +extern int ZEXPORT unzGoToNextFile(unzFile file); /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); +extern int ZEXPORT unzLocateFile(unzFile file, + const char *szFileName, + int iCaseSensitivity); /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare @@ -285,28 +285,28 @@ extern int ZEXPORT unzGoToFilePos64( /* ****************************************** */ -extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, - unz_file_info64 *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); +extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize); -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); +extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize); /* Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about + if pfile_info!=NULL, the *pfile_info structure will contain some info about the current file - if szFileName!=NULL, the filemane string will be copied in szFileName + if szFileName!=NULL, the filename string will be copied in szFileName (fileNameBufferSize is the size of the buffer) if extraField!=NULL, the extra field information will be copied in extraField (extraFieldBufferSize is the size of the buffer). @@ -318,7 +318,7 @@ extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, /** Addition for GDAL : START */ -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file); /** Addition for GDAL : END */ @@ -328,24 +328,24 @@ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); from it, and close it (you can close it before reading all the file) */ -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +extern int ZEXPORT unzOpenCurrentFile(unzFile file); /* Open for reading data the current file in the zipfile. If there is no error, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, - const char* password)); +extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, + const char* password); /* Open for reading data the current file in the zipfile. password is a crypting password If there is no error, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); +extern int ZEXPORT unzOpenCurrentFile2(unzFile file, + int* method, + int* level, + int raw); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 @@ -355,11 +355,11 @@ extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, but you CANNOT set method parameter as NULL */ -extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, - int* method, - int* level, - int raw, - const char* password)); +extern int ZEXPORT unzOpenCurrentFile3(unzFile file, + int* method, + int* level, + int raw, + const char* password); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 @@ -370,41 +370,41 @@ extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, */ -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +extern int ZEXPORT unzCloseCurrentFile(unzFile file); /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); +extern int ZEXPORT unzReadCurrentFile(unzFile file, + voidp buf, + unsigned len); /* Read bytes from the current file (opened by unzOpenCurrentFile) buf contain buffer where data must be copied len the size of buf. - return the number of byte copied if somes bytes are copied + return the number of byte copied if some bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ -extern z_off_t ZEXPORT unztell OF((unzFile file)); +extern z_off_t ZEXPORT unztell(unzFile file); -extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +extern ZPOS64_T ZEXPORT unztell64(unzFile file); /* Give the current position in uncompressed data */ -extern int ZEXPORT unzeof OF((unzFile file)); +extern int ZEXPORT unzeof(unzFile file); /* return 1 if the end of file was reached, 0 elsewhere */ -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); +extern int ZEXPORT unzGetLocalExtrafield(unzFile file, + voidp buf, + unsigned len); /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is diff --git a/contrib/zip/.gitattributes b/contrib/zip/.gitattributes new file mode 100644 index 000000000..15a5c5809 --- /dev/null +++ b/contrib/zip/.gitattributes @@ -0,0 +1 @@ +*.h linguist-language=C diff --git a/contrib/zip/.gitignore b/contrib/zip/.gitignore new file mode 100644 index 000000000..a5900dbcd --- /dev/null +++ b/contrib/zip/.gitignore @@ -0,0 +1,60 @@ +/build/ +/test/build/ +/xcodeproj/ +/infer-out/ +.vscode/ +Testing/ + +# 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/ + diff --git a/contrib/zip/.travis.sh b/contrib/zip/.travis.sh deleted file mode 100755 index 9cb03ee87..000000000 --- a/contrib/zip/.travis.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# Build script for travis-ci.org builds. -# -if [ $ANALYZE = "true" ] && [ "$CC" = "clang" ]; then - # scan-build -h - scan-build cmake -G "Unix Makefiles" - scan-build -enable-checker security.FloatLoopCounter \ - -enable-checker security.insecureAPI.UncheckedReturn \ - --status-bugs -v \ - make -j 8 \ - make -j 8 test -else - cmake -DCMAKE_BUILD_TYPE=Debug -DSANITIZE_ADDRESS=On -DCMAKE_INSTALL_PREFIX=_install - make -j 8 - make install - ASAN_OPTIONS=detect_leaks=0 LSAN_OPTIONS=verbosity=1:log_threads=1 ctest -V -fi diff --git a/contrib/zip/.travis.yml b/contrib/zip/.travis.yml deleted file mode 100644 index 42f84dd25..000000000 --- a/contrib/zip/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: c -addons: - apt: - packages: &1 - - lcov -# Compiler selection -compiler: - - clang - - gcc -env: - - ANALYZE=false - - ANALYZE=true -# Build steps -script: - - ./.travis.sh -after_success: - # Creating report - - cmake -DENABLE_COVERAGE=ON - - make - - make test - # Uploading report to CodeCov - - bash <(curl -s https://codecov.io/bash) diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt index bba4e7bde..8f10e0c10 100644 --- a/contrib/zip/CMakeLists.txt +++ b/contrib/zip/CMakeLists.txt @@ -1,27 +1,47 @@ -cmake_minimum_required(VERSION 3.4) +cmake_minimum_required(VERSION 3.14) project(zip LANGUAGES C - VERSION "0.1.19") + VERSION "0.3.0") set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) set(CMAKE_VERBOSE_MAKEFILE ON) -option(CMAKE_DISABLE_TESTING "Disable test creation" OFF) + +# Enable building tests only if the project is being built as a standalone one +if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + option(CMAKE_DISABLE_TESTING "Disable test creation" OFF) +else () + option(CMAKE_DISABLE_TESTING "Disable test creation" ON) +endif () + +option(CMAKE_ENABLE_SANITIZERS "Enable zip sanitizers" OFF) +option(ZIP_STATIC_PIC "Build static zip with PIC" ON) +option(ZIP_BUILD_DOCS "Generate API documentation with Doxygen" OFF) + +if(ZIP_ENABLE_SHARABLE_FILE_OPEN) + add_definitions(-DZIP_ENABLE_SHARABLE_FILE_OPEN) +endif() + +if(CMAKE_SIZEOF_VOID_P EQUAL 4) + # large file support + add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64) +endif() # zip set(SRC src/miniz.h src/zip.h src/zip.c) -# 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) +add_library(${PROJECT_NAME} ${SRC}) +add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -# static and shared libraries built from the same object files -if (BUILD_SHARED_LIBS) - add_library(${PROJECT_NAME} SHARED $) - include(GenerateExportHeader) - generate_export_header(${PROJECT_NAME}) -else() - add_library(${PROJECT_NAME} STATIC $) +if(ZIP_STATIC_PIC) + set_property(TARGET ${PROJECT_NAME} PROPERTY POSITION_INDEPENDENT_CODE 1) +endif() + +set_property(TARGET ${PROJECT_NAME} PROPERTY C_VISIBILITY_PRESET hidden) +if(BUILD_SHARED_LIBS) + target_compile_definitions(${PROJECT_NAME} + PUBLIC ZIP_SHARED + PRIVATE ZIP_BUILD_SHARED + ) endif() target_include_directories(${PROJECT_NAME} PUBLIC @@ -33,24 +53,26 @@ target_include_directories(${PROJECT_NAME} PUBLIC if (NOT CMAKE_DISABLE_TESTING) enable_testing() add_subdirectory(test) +endif() +if (CMAKE_ENABLE_SANITIZERS) find_package(Sanitizers) - add_sanitizers(${PROJECT_NAME} ${test_out}) + add_sanitizers(${PROJECT_NAME}) endif() +set(CMAKE_C_STANDARD 90) 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") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -pedantic") endif (MSVC) #### -# Installation (https://github.com/forexample/package-example) { - set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") set(INCLUDE_INSTALL_DIR "include") @@ -62,7 +84,7 @@ set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") set(NAMESPACE "${PROJECT_NAME}::") -# Include module with fuction 'write_basic_package_version_file' +# Include module with function 'write_basic_package_version_file' include(CMakePackageConfigHelpers) # Note: PROJECT_VERSION is used as a VERSION @@ -90,8 +112,6 @@ install( DESTINATION "${CONFIG_INSTALL_DIR}" ) -# } - install(TARGETS ${PROJECT_NAME} EXPORT ${TARGETS_EXPORT_NAME} RUNTIME DESTINATION bin @@ -112,8 +132,8 @@ if(NOT TARGET uninstall) COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake) endif() -find_package(Doxygen) -if(DOXYGEN_FOUND) +if(ZIP_BUILD_DOCS) + find_package(Doxygen REQUIRED) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile diff --git a/contrib/zip/CONTRIBUTING.md b/contrib/zip/CONTRIBUTING.md new file mode 100644 index 000000000..bec8e0971 --- /dev/null +++ b/contrib/zip/CONTRIBUTING.md @@ -0,0 +1,9 @@ +# 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 +``` diff --git a/contrib/zip/Doxyfile.in b/contrib/zip/Doxyfile.in new file mode 100644 index 000000000..7f03b1833 --- /dev/null +++ b/contrib/zip/Doxyfile.in @@ -0,0 +1,2480 @@ +# Doxyfile 1.8.14 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = zip + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = @ZIP_VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = @CMAKE_CURRENT_SOURCE_DIR@/src + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = YES + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = YES + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = YES + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = NO + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop on Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/ + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /