From d74a1149b7480ba73ae5df92c772f6e1cf31b568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Tue, 18 Aug 2015 11:36:32 +0300 Subject: [PATCH 01/77] MD5: Fix quaternion conversions Some of the quaternions loaded from MD5 files were not converted to follow Assimp conventions. https://github.com/assimp/assimp/issues/495 --- code/MD5Loader.cpp | 6 ------ code/MD5Parser.h | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/code/MD5Loader.cpp b/code/MD5Loader.cpp index 6628aa346..6f0780e6d 100644 --- a/code/MD5Loader.cpp +++ b/code/MD5Loader.cpp @@ -285,9 +285,6 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo aiQuaternion quat; MD5::ConvertQuaternion ( bones[i].mRotationQuat, quat ); - // FIX to get to Assimp's quaternion conventions - quat.w *= -1.f; - bones[i].mTransform = aiMatrix4x4 ( quat.GetMatrix()); bones[i].mTransform.a4 = bones[i].mPositionXYZ.x; bones[i].mTransform.b4 = bones[i].mPositionXYZ.y; @@ -656,9 +653,6 @@ void MD5Importer::LoadMD5AnimFile () MD5::ConvertQuaternion(vTemp, qKey->mValue); qKey->mTime = vKey->mTime = dTime; - - // we need this to get to Assimp quaternion conventions - qKey->mValue.w *= -1.f; } } diff --git a/code/MD5Parser.h b/code/MD5Parser.h index fd13961e2..e08d6d8b4 100644 --- a/code/MD5Parser.h +++ b/code/MD5Parser.h @@ -262,6 +262,9 @@ inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) { if (t < 0.0f) out.w = 0.0f; else out.w = std::sqrt (t); + + // Assimp convention. + out.w *= -1.f; } // --------------------------------------------------------------------------- From fff2c4141e33ab3edf4d7b7ba31c68f12c91c1c4 Mon Sep 17 00:00:00 2001 From: abma Date: Wed, 2 Sep 2015 09:56:58 +0200 Subject: [PATCH 02/77] fix #634 --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1a13ef6f..166791a04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,9 @@ if( CMAKE_COMPILER_IS_MINGW ) endif() if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # this is a very important switch and some libraries seem now to have it.... + if (BUILD_SHARED_LIBS AND CMAKE_SIZEOF_VOID_P EQUAL 8) # -fPIC is only required for shared libs on 64 bit + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + endif() # hide all not-exported symbols set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall" ) elseif(MSVC) From d49e47c25cca464a3fe088d351f76cd006e09f24 Mon Sep 17 00:00:00 2001 From: abma Date: Wed, 2 Sep 2015 10:04:28 +0200 Subject: [PATCH 03/77] fix #431 --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 166791a04..3f68db817 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ execute_process( WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET ) # Get the latest abbreviated commit hash of the working branch @@ -35,6 +36,7 @@ execute_process( WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET ) if(NOT GIT_COMMIT_HASH) From e159728307f17888b8b3ab4f23cf2143562c1c10 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 15 Sep 2015 08:55:40 +0200 Subject: [PATCH 04/77] Update Readme.md Update contect info: now add an irc channel on freenode --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index bc94885b3..ed1911a78 100644 --- a/Readme.md +++ b/Readme.md @@ -113,6 +113,7 @@ If the docs don't solve your problem, ask on [StackOverflow](http://stackoverflo For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_ [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) +And we also have an IRC-channel at freenode: #assetimporterlib . ### Contributing ### Contributions to assimp are highly appreciated. The easiest way to get involved is to submit From 367c9980b2781ec13e8a058541e724856ec36e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Mathisen?= Date: Sun, 20 Sep 2015 17:15:01 +0200 Subject: [PATCH 05/77] Add Boost 1.59 --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f68db817..cbb7bd641 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,7 +123,9 @@ IF ( ASSIMP_ENABLE_BOOST_WORKAROUND ) MESSAGE( STATUS "Building a non-boost version of Assimp." ) ELSE ( ASSIMP_ENABLE_BOOST_WORKAROUND ) SET( Boost_DETAILED_FAILURE_MSG ON ) - SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57" "1.57.0" "1.58" "1.58.0" ) + IF ( NOT Boost_ADDITIONAL_VERSIONS ) + SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57" "1.57.0" "1.58" "1.58.0" "1.59" "1.59.0") + ENDIF ( NOT Boost_ADDITIONAL_VERSIONS ) FIND_PACKAGE( Boost ) IF ( NOT Boost_FOUND ) MESSAGE( FATAL_ERROR From f2c2bc6945b787b3bc8105a3173c0504a91ee185 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 21 Sep 2015 17:31:27 +0200 Subject: [PATCH 06/77] CMake: add windows 8.1 search path for DirectX SDK, closes assimp/assimp/issues/631 --- cmake-modules/FindDirectX.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake-modules/FindDirectX.cmake b/cmake-modules/FindDirectX.cmake index 38a861a83..707043142 100644 --- a/cmake-modules/FindDirectX.cmake +++ b/cmake-modules/FindDirectX.cmake @@ -35,6 +35,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK "C:/Program Files (x86)/Microsoft DirectX SDK*" "C:/apps/Microsoft DirectX SDK*" "C:/Program Files/Microsoft DirectX SDK*" + "C:/Program Files (x86)/Windows Kits/8.1" "$ENV{ProgramFiles}/Microsoft DirectX SDK*" ) create_search_paths(DirectX) From ca6296f60999d113be01a35cf9812cae49725860 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 21 Sep 2015 17:33:41 +0200 Subject: [PATCH 07/77] STLLoader: mak functions local. --- code/STLLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index ad445efdb..4dc69b4bd 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -74,7 +74,7 @@ static const aiImporterDesc desc = { // 1) 80 byte header // 2) 4 byte face count // 3) 50 bytes per face -bool IsBinarySTL(const char* buffer, unsigned int fileSize) { +static bool IsBinarySTL(const char* buffer, unsigned int fileSize) { if( fileSize < 84 ) { return false; } @@ -88,7 +88,7 @@ bool IsBinarySTL(const char* buffer, unsigned int fileSize) { // An ascii STL buffer will begin with "solid NAME", where NAME is optional. // Note: The "solid NAME" check is necessary, but not sufficient, to determine // if the buffer is ASCII; a binary header could also begin with "solid NAME". -bool IsAsciiSTL(const char* buffer, unsigned int fileSize) { +static bool IsAsciiSTL(const char* buffer, unsigned int fileSize) { if (IsBinarySTL(buffer, fileSize)) return false; From 34ee4c4b9a1b862ad025e89e018ebfc763ef950c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 21 Sep 2015 20:43:58 +0200 Subject: [PATCH 08/77] DefaultIOSystem close assimp/assimp/issues/108 : use correct macro to detect vs-compiler. --- code/DefaultIOSystem.cpp | 17 ++++++++++------- code/DefaultIOSystem.h | 6 +++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 32ea03b71..b3f8dc093 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -135,8 +135,8 @@ inline void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); char* ret; -#ifdef _WIN32 - ret = ::_fullpath(_out, in,PATHLIMIT); +#if defined _WIN32 && !defined __GNUC__ + ret = ::_fullpath( _out, in, PATHLIMIT ); #else // use realpath ret = realpath(in, _out); @@ -167,8 +167,8 @@ bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const return !ASSIMP_stricmp(temp1,temp2); } - -std::string DefaultIOSystem::fileName(std::string path) +// ------------------------------------------------------------------------------------------------ +std::string DefaultIOSystem::fileName( const std::string &path ) { std::string ret = path; std::size_t last = ret.find_last_of("\\/"); @@ -177,7 +177,8 @@ std::string DefaultIOSystem::fileName(std::string path) } -std::string DefaultIOSystem::completeBaseName(std::string path) +// ------------------------------------------------------------------------------------------------ +std::string DefaultIOSystem::completeBaseName( const std::string &path ) { std::string ret = fileName(path); std::size_t pos = ret.find_last_of('.'); @@ -185,8 +186,8 @@ std::string DefaultIOSystem::completeBaseName(std::string path) return ret; } - -std::string DefaultIOSystem::absolutePath(std::string path) +// ------------------------------------------------------------------------------------------------ +std::string DefaultIOSystem::absolutePath( const std::string &path ) { std::string ret = path; std::size_t last = ret.find_last_of("\\/"); @@ -194,4 +195,6 @@ std::string DefaultIOSystem::absolutePath(std::string path) return ret; } +// ------------------------------------------------------------------------------------------------ + #undef PATHLIMIT diff --git a/code/DefaultIOSystem.h b/code/DefaultIOSystem.h index b46169f79..cc2118fb9 100644 --- a/code/DefaultIOSystem.h +++ b/code/DefaultIOSystem.h @@ -80,17 +80,17 @@ public: /** @brief get the file name of a full filepath * example: /tmp/archive.tar.gz -> archive.tar.gz */ - static std::string fileName(std::string path); + static std::string fileName( const std::string &path ); /** @brief get the complete base name of a full filepath * example: /tmp/archive.tar.gz -> archive.tar */ - static std::string completeBaseName(std::string path); + static std::string completeBaseName( const std::string &path); /** @brief get the path of a full filepath * example: /tmp/archive.tar.gz -> /tmp/ */ - static std::string absolutePath(std::string path); + static std::string absolutePath( const std::string &path); }; } //!ns Assimp From ef6baa0acfad057d49b10dc98d9dcaff626c69a7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Sep 2015 00:23:33 +0200 Subject: [PATCH 09/77] DefaultIOSystem: use correct define to detect Visual Studi compiler. --- code/DefaultIOSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index b3f8dc093..d4f120c3b 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -135,7 +135,7 @@ inline void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); char* ret; -#if defined _WIN32 && !defined __GNUC__ +#ifdef _MSC_VER ret = ::_fullpath( _out, in, PATHLIMIT ); #else // use realpath From 3fc251b326249c6ed51ea65b6d259c45a3e1f06b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 24 Sep 2015 00:57:47 +0200 Subject: [PATCH 10/77] BaseImporter: fix typo and rename attributes for better readability. --- code/BaseImporter.cpp | 10 +++++----- code/BaseImporter.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 3c8d9e39b..071411642 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -63,7 +63,7 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer BaseImporter::BaseImporter() -: progress() +: m_progress() { // nothing to do here } @@ -79,8 +79,8 @@ BaseImporter::~BaseImporter() // Imports the given file and returns the imported data. aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) { - progress = pImp->GetProgressHandler(); - ai_assert(progress); + m_progress = pImp->GetProgressHandler(); + ai_assert(m_progress); // Gather configuration properties for this run SetupProperties( pImp ); @@ -98,8 +98,8 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, } catch( const std::exception& err ) { // extract error description - mErrorText = err.what(); - DefaultLogger::get()->error(mErrorText); + m_ErrorText = err.what(); + DefaultLogger::get()->error(m_ErrorText); return NULL; } diff --git a/code/BaseImporter.h b/code/BaseImporter.h index 2234d7116..e8ed7460d 100644 --- a/code/BaseImporter.h +++ b/code/BaseImporter.h @@ -181,7 +181,7 @@ public: * string if there was no error. */ const std::string& GetErrorText() const { - return mErrorText; + return m_ErrorText; } // ------------------------------------------------------------------- @@ -362,10 +362,10 @@ public: // static utilities protected: /** Error description in case there was one. */ - std::string mErrorText; + std::string m_ErrorText; /** Currently set progress handler */ - ProgressHandler* progress; + ProgressHandler* m_progress; }; From d06945f17e616b2fa633aa85c02ff03c0c01e14a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 24 Sep 2015 23:51:04 +0200 Subject: [PATCH 11/77] DefaultIOSystem: fix issue assimp/assimp/issues/660 by checking for _WIN32 as well. --- code/DefaultIOSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index d4f120c3b..1251b6c2c 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -135,7 +135,7 @@ inline void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); char* ret; -#ifdef _MSC_VER +#if defined _WIN32 && defined _MSC_VER ret = ::_fullpath( _out, in, PATHLIMIT ); #else // use realpath From f5c8f7b5e504f37710a04beb58b0b67e5f0e7452 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 27 Sep 2015 01:02:12 +0200 Subject: [PATCH 12/77] DefaultIOSystem: close cygwin issue assimp/assimp/issues/660. --- code/DefaultIOSystem.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 1251b6c2c..1e7aaf8b9 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -135,11 +135,11 @@ inline void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); char* ret; -#if defined _WIN32 && defined _MSC_VER - ret = ::_fullpath( _out, in, PATHLIMIT ); +if defined( _MSC_VER ) || defined( __MINGW32__ ) + ret = ::_fullpath( _out, in, PATHLIMIT ); #else - // use realpath - ret = realpath(in, _out); + // use realpath + ret = realpath(in, _out); #endif if(!ret) { // preserve the input path, maybe someone else is able to fix From 1fbc0cc2767eb96ce2765b4d260db4a910cbc803 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 27 Sep 2015 10:51:33 +0200 Subject: [PATCH 13/77] DefaultIOSystem: fix typo in macro. --- code/BaseImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 071411642..303c06779 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -274,7 +274,7 @@ void BaseImporter::GetExtensionList(std::set& extensions) for (unsigned int i = 0; i < num; ++i) { // also check against big endian versions of tokens with size 2,4 - // that's just for convinience, the chance that we cause conflicts + // that's just for convenience, the chance that we cause conflicts // is quite low and it can save some lines and prevent nasty bugs if (2 == size) { uint16_t rev = *magic_u16; From 7ed32fd5a9bdefb23fb281ec98dce3383383e51a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 27 Sep 2015 20:49:15 +0200 Subject: [PATCH 14/77] fix typo. --- code/DefaultIOSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 1e7aaf8b9..89d40e2a5 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -135,7 +135,7 @@ inline void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); char* ret; -if defined( _MSC_VER ) || defined( __MINGW32__ ) +#if defined( _MSC_VER ) || defined( __MINGW32__ ) ret = ::_fullpath( _out, in, PATHLIMIT ); #else // use realpath From 2e725c0dc525072ba5b8625a79779401022f785b Mon Sep 17 00:00:00 2001 From: Tcll Date: Mon, 28 Sep 2015 14:15:06 -0400 Subject: [PATCH 15/77] Added auto-detection of numpy If numpy is not installed, pyassimp returns lists to allow the user to manage the data type. --- port/PyAssimp/pyassimp/core.py | 67 +++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index 29550eb35..f035b35e5 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -10,7 +10,9 @@ if sys.version_info < (2,6): import ctypes import os -import numpy + +try: import numpy +except: numpy = None import logging logger = logging.getLogger("pyassimp") @@ -33,12 +35,30 @@ _assimp_lib = AssimpLib() def make_tuple(ai_obj, type = None): res = None + + #notes: + # ai_obj._fields_ = [ ("attr", c_type), ... ] + # getattr(ai_obj, e[0]).__class__ == float + if isinstance(ai_obj, structs.Matrix4x4): - res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_]).reshape((4,4)) + if numpy: + res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_]).reshape((4,4)) + #import pdb;pdb.set_trace() + else: + res = [getattr(ai_obj, e[0]) for e in ai_obj._fields_] + res = [res[i:i+4] for i in xrange(0,16,4)] elif isinstance(ai_obj, structs.Matrix3x3): - res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_]).reshape((3,3)) + if numpy: + res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_]).reshape((3,3)) + else: + res = [getattr(ai_obj, e[0]) for e in ai_obj._fields_] + res = [res[i:i+3] for i in xrange(0,9,3)] else: - res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_]) + if numpy: + res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_]) + else: + res = [getattr(ai_obj, e[0]) for e in ai_obj._fields_] + return res # It is faster and more correct to have an init function for each assimp class @@ -135,9 +155,14 @@ def _init(self, target = None, parent = None): try: if obj._type_ in structs.assimp_structs_as_tuple: - setattr(target, name, numpy.array([make_tuple(obj[i]) for i in range(length)], dtype=numpy.float32)) + if numpy: + setattr(target, name, numpy.array([make_tuple(obj[i]) for i in range(length)], dtype=numpy.float32)) - logger.debug(str(self) + ": Added an array of numpy arrays (type "+ str(type(obj)) + ") as self." + name) + logger.debug(str(self) + ": Added an array of numpy arrays (type "+ str(type(obj)) + ") as self." + name) + else: + setattr(target, name, [make_tuple(obj[i]) for i in range(length)]) + + logger.debug(str(self) + ": Added a list of lists (type "+ str(type(obj)) + ") as self." + name) else: setattr(target, name, [obj[i] for i in range(length)]) #TODO: maybe not necessary to recreate an array? @@ -292,7 +317,10 @@ def release(scene): def _finalize_texture(tex, target): setattr(target, "achformathint", tex.achFormatHint) - data = numpy.array([make_tuple(getattr(tex, "pcData")[i]) for i in range(tex.mWidth * tex.mHeight)]) + if numpy: + data = numpy.array([make_tuple(getattr(tex, "pcData")[i]) for i in range(tex.mWidth * tex.mHeight)]) + else: + data = [make_tuple(getattr(tex, "pcData")[i]) for i in range(tex.mWidth * tex.mHeight)] setattr(target, "data", data) def _finalize_mesh(mesh, target): @@ -308,11 +336,18 @@ def _finalize_mesh(mesh, target): def fill(name): mAttr = getattr(mesh, name) - if mAttr: - data = numpy.array([make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)], dtype=numpy.float32) - setattr(target, name[1:].lower(), data) + if numpy: + if mAttr: + data = numpy.array([make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)], dtype=numpy.float32) + setattr(target, name[1:].lower(), data) + else: + setattr(target, name[1:].lower(), numpy.array([], dtype="float32")) else: - setattr(target, name[1:].lower(), numpy.array([], dtype="float32")) + if mAttr: + data = [make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)] + setattr(target, name[1:].lower(), data) + else: + setattr(target, name[1:].lower(), []) def fillarray(name): mAttr = getattr(mesh, name) @@ -322,7 +357,10 @@ def _finalize_mesh(mesh, target): if mSubAttr: data.append([make_tuple(getattr(mesh, name)[index][i]) for i in range(nb_vertices)]) - setattr(target, name[1:].lower(), numpy.array(data, dtype=numpy.float32)) + if numpy: + setattr(target, name[1:].lower(), numpy.array(data, dtype=numpy.float32)) + else: + setattr(target, name[1:].lower(), data) fill("mNormals") fill("mTangents") @@ -332,7 +370,10 @@ def _finalize_mesh(mesh, target): fillarray("mTextureCoords") # prepare faces - faces = numpy.array([f.indices for f in target.faces], dtype=numpy.int32) + if numpy: + faces = numpy.array([f.indices for f in target.faces], dtype=numpy.int32) + else: + faces = [f.indices for f in target.faces] setattr(target, 'faces', faces) From 5ce968c67f2153435b781cf5704e2f63201f9b11 Mon Sep 17 00:00:00 2001 From: Tcll Date: Mon, 28 Sep 2015 14:18:22 -0400 Subject: [PATCH 16/77] Added auto-detection of numpy --- port/PyAssimp/pyassimp/helper.py | 85 +++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/port/PyAssimp/pyassimp/helper.py b/port/PyAssimp/pyassimp/helper.py index ccfd8d2b5..249a0f2ab 100644 --- a/port/PyAssimp/pyassimp/helper.py +++ b/port/PyAssimp/pyassimp/helper.py @@ -8,8 +8,9 @@ import os import ctypes from ctypes import POINTER import operator -import numpy -from numpy import linalg + +try: import numpy +except: numpy = None import logging;logger = logging.getLogger("pyassimp") @@ -45,20 +46,88 @@ def vec2tuple(x): def transform(vector3, matrix4x4): """ Apply a transformation matrix on a 3D vector. - :param vector3: a numpy array with 3 elements - :param matrix4x4: a numpy 4x4 matrix + :param vector3: array with 3 elements + :param matrix4x4: 4x4 matrix """ - return numpy.dot(matrix4x4, numpy.append(vector3, 1.)) - + if numpy: + return numpy.dot(matrix4x4, numpy.append(vector3, 1.)) + else: + m0,m1,m2,m3 = matrix4x4; x,y,z = vector3 + return [ + m0[0]*x + m0[1]*y + m0[2]*z + m0[3], + m1[0]*x + m1[1]*y + m1[2]*z + m1[3], + m2[0]*x + m2[1]*y + m2[2]*z + m2[3], + m3[0]*x + m3[1]*y + m3[2]*z + m3[3] + ] + +def _inv(matrix4x4): + m0,m1,m2,m3 = matrix4x4 + + det = m0[3]*m1[2]*m2[1]*m3[0] - m0[2]*m1[3]*m2[1]*m3[0] - \ + m0[3]*m1[1]*m2[2]*m3[0] + m0[1]*m1[3]*m2[2]*m3[0] + \ + m0[2]*m1[1]*m2[3]*m3[0] - m0[1]*m1[2]*m2[3]*m3[0] - \ + m0[3]*m1[2]*m2[0]*m3[1] + m0[2]*m1[3]*m2[0]*m3[1] + \ + m0[3]*m1[0]*m2[2]*m3[1] - m0[0]*m1[3]*m2[2]*m3[1] - \ + m0[2]*m1[0]*m2[3]*m3[1] + m0[0]*m1[2]*m2[3]*m3[1] + \ + m0[3]*m1[1]*m2[0]*m3[2] - m0[1]*m1[3]*m2[0]*m3[2] - \ + m0[3]*m1[0]*m2[1]*m3[2] + m0[0]*m1[3]*m2[1]*m3[2] + \ + m0[1]*m1[0]*m2[3]*m3[2] - m0[0]*m1[1]*m2[3]*m3[2] - \ + m0[2]*m1[1]*m2[0]*m3[3] + m0[1]*m1[2]*m2[0]*m3[3] + \ + m0[2]*m1[0]*m2[1]*m3[3] - m0[0]*m1[2]*m2[1]*m3[3] - \ + m0[1]*m1[0]*m2[2]*m3[3] + m0[0]*m1[1]*m2[2]*m3[3] + + return[[( m1[2]*m2[3]*m3[1] - m1[3]*m2[2]*m3[1] + m1[3]*m2[1]*m3[2] - m1[1]*m2[3]*m3[2] - m1[2]*m2[1]*m3[3] + m1[1]*m2[2]*m3[3]) /det, + ( m0[3]*m2[2]*m3[1] - m0[2]*m2[3]*m3[1] - m0[3]*m2[1]*m3[2] + m0[1]*m2[3]*m3[2] + m0[2]*m2[1]*m3[3] - m0[1]*m2[2]*m3[3]) /det, + ( m0[2]*m1[3]*m3[1] - m0[3]*m1[2]*m3[1] + m0[3]*m1[1]*m3[2] - m0[1]*m1[3]*m3[2] - m0[2]*m1[1]*m3[3] + m0[1]*m1[2]*m3[3]) /det, + ( m0[3]*m1[2]*m2[1] - m0[2]*m1[3]*m2[1] - m0[3]*m1[1]*m2[2] + m0[1]*m1[3]*m2[2] + m0[2]*m1[1]*m2[3] - m0[1]*m1[2]*m2[3]) /det], + [( m1[3]*m2[2]*m3[0] - m1[2]*m2[3]*m3[0] - m1[3]*m2[0]*m3[2] + m1[0]*m2[3]*m3[2] + m1[2]*m2[0]*m3[3] - m1[0]*m2[2]*m3[3]) /det, + ( m0[2]*m2[3]*m3[0] - m0[3]*m2[2]*m3[0] + m0[3]*m2[0]*m3[2] - m0[0]*m2[3]*m3[2] - m0[2]*m2[0]*m3[3] + m0[0]*m2[2]*m3[3]) /det, + ( m0[3]*m1[2]*m3[0] - m0[2]*m1[3]*m3[0] - m0[3]*m1[0]*m3[2] + m0[0]*m1[3]*m3[2] + m0[2]*m1[0]*m3[3] - m0[0]*m1[2]*m3[3]) /det, + ( m0[2]*m1[3]*m2[0] - m0[3]*m1[2]*m2[0] + m0[3]*m1[0]*m2[2] - m0[0]*m1[3]*m2[2] - m0[2]*m1[0]*m2[3] + m0[0]*m1[2]*m2[3]) /det], + [( m1[1]*m2[3]*m3[0] - m1[3]*m2[1]*m3[0] + m1[3]*m2[0]*m3[1] - m1[0]*m2[3]*m3[1] - m1[1]*m2[0]*m3[3] + m1[0]*m2[1]*m3[3]) /det, + ( m0[3]*m2[1]*m3[0] - m0[1]*m2[3]*m3[0] - m0[3]*m2[0]*m3[1] + m0[0]*m2[3]*m3[1] + m0[1]*m2[0]*m3[3] - m0[0]*m2[1]*m3[3]) /det, + ( m0[1]*m1[3]*m3[0] - m0[3]*m1[1]*m3[0] + m0[3]*m1[0]*m3[1] - m0[0]*m1[3]*m3[1] - m0[1]*m1[0]*m3[3] + m0[0]*m1[1]*m3[3]) /det, + ( m0[3]*m1[1]*m2[0] - m0[1]*m1[3]*m2[0] - m0[3]*m1[0]*m2[1] + m0[0]*m1[3]*m2[1] + m0[1]*m1[0]*m2[3] - m0[0]*m1[1]*m2[3]) /det], + [( m1[2]*m2[1]*m3[0] - m1[1]*m2[2]*m3[0] - m1[2]*m2[0]*m3[1] + m1[0]*m2[2]*m3[1] + m1[1]*m2[0]*m3[2] - m1[0]*m2[1]*m3[2]) /det, + ( m0[1]*m2[2]*m3[0] - m0[2]*m2[1]*m3[0] + m0[2]*m2[0]*m3[1] - m0[0]*m2[2]*m3[1] - m0[1]*m2[0]*m3[2] + m0[0]*m2[1]*m3[2]) /det, + ( m0[2]*m1[1]*m3[0] - m0[1]*m1[2]*m3[0] - m0[2]*m1[0]*m3[1] + m0[0]*m1[2]*m3[1] + m0[1]*m1[0]*m3[2] - m0[0]*m1[1]*m3[2]) /det, + ( m0[1]*m1[2]*m2[0] - m0[2]*m1[1]*m2[0] + m0[2]*m1[0]*m2[1] - m0[0]*m1[2]*m2[1] - m0[1]*m1[0]*m2[2] + m0[0]*m1[1]*m2[2]) /det]] def get_bounding_box(scene): bb_min = [1e10, 1e10, 1e10] # x,y,z bb_max = [-1e10, -1e10, -1e10] # x,y,z - return get_bounding_box_for_node(scene.rootnode, bb_min, bb_max, linalg.inv(scene.rootnode.transformation)) + inv = numpy.linalg.inv if numpy else _inv + return get_bounding_box_for_node(scene.rootnode, bb_min, bb_max, inv(scene.rootnode.transformation)) def get_bounding_box_for_node(node, bb_min, bb_max, transformation): - transformation = numpy.dot(transformation, node.transformation) + if numpy: + transformation = numpy.dot(transformation, node.transformation) + else: + t0,t1,t2,t3 = transformation + T0,T1,T2,T3 = node.transformation + transformation = [ [ + t0[0]*T0[0] + t0[1]*T1[0] + t0[2]*T2[0] + t0[3]*T3[0], + t0[0]*T0[1] + t0[1]*T1[1] + t0[2]*T2[1] + t0[3]*T3[1], + t0[0]*T0[2] + t0[1]*T1[2] + t0[2]*T2[2] + t0[3]*T3[2], + t0[0]*T0[3] + t0[1]*T1[3] + t0[2]*T2[3] + t0[3]*T3[3] + ],[ + t1[0]*T0[0] + t1[1]*T1[0] + t1[2]*T2[0] + t1[3]*T3[0], + t1[0]*T0[1] + t1[1]*T1[1] + t1[2]*T2[1] + t1[3]*T3[1], + t1[0]*T0[2] + t1[1]*T1[2] + t1[2]*T2[2] + t1[3]*T3[2], + t1[0]*T0[3] + t1[1]*T1[3] + t1[2]*T2[3] + t1[3]*T3[3] + ],[ + t2[0]*T0[0] + t2[1]*T1[0] + t2[2]*T2[0] + t2[3]*T3[0], + t2[0]*T0[1] + t2[1]*T1[1] + t2[2]*T2[1] + t2[3]*T3[1], + t2[0]*T0[2] + t2[1]*T1[2] + t2[2]*T2[2] + t2[3]*T3[2], + t2[0]*T0[3] + t2[1]*T1[3] + t2[2]*T2[3] + t2[3]*T3[3] + ],[ + t3[0]*T0[0] + t3[1]*T1[0] + t3[2]*T2[0] + t3[3]*T3[0], + t3[0]*T0[1] + t3[1]*T1[1] + t3[2]*T2[1] + t3[3]*T3[1], + t3[0]*T0[2] + t3[1]*T1[2] + t3[2]*T2[2] + t3[3]*T3[2], + t3[0]*T0[3] + t3[1]*T1[3] + t3[2]*T2[3] + t3[3]*T3[3] + ] ] + for mesh in node.meshes: for v in mesh.vertices: v = transform(v, transformation) From 6f0bc9bcb29fa0c9f23e89e2619ba380d2ff18bb Mon Sep 17 00:00:00 2001 From: Lectem Date: Wed, 30 Sep 2015 09:16:18 -0400 Subject: [PATCH 17/77] remove memory.h dependancy Some embedded (or exotic) systems won't provide this header, and it seems to be unused (since memcpy is in string.h). Tested on MinGW and VS2015. --- include/assimp/types.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/assimp/types.h b/include/assimp/types.h index 8e784cfe8..82be2d62f 100644 --- a/include/assimp/types.h +++ b/include/assimp/types.h @@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Some runtime headers #include -#include #include #include #include From 4a8b459706bfc9e311535352fd6cf460977f1fe9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 1 Oct 2015 20:29:15 +0200 Subject: [PATCH 18/77] OpenDDLParser: latest greatest. --- code/CMakeLists.txt | 3 + contrib/openddlparser/code/DDLNode.cpp | 10 +- contrib/openddlparser/code/OpenDDLParser.cpp | 64 +++-- contrib/openddlparser/code/Value.cpp | 43 +++- .../include/openddlparser/DDLNode.h | 4 + .../include/openddlparser/OpenDDLCommon.h | 238 ++++++++---------- .../include/openddlparser/OpenDDLParser.h | 73 +++++- .../include/openddlparser/Value.h | 18 +- include/assimp/material.h | 24 +- test/unit/utRemoveComments.cpp | 11 +- 10 files changed, 295 insertions(+), 193 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index c3302ee98..3d19bf0ef 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -632,10 +632,13 @@ SOURCE_GROUP( unzip FILES ${unzip_SRCS}) SET ( openddl_parser_SRCS ../contrib/openddlparser/code/OpenDDLParser.cpp ../contrib/openddlparser/code/DDLNode.cpp + ../contrib/openddlparser/code/OpenDDLCommon.cpp + ../contrib/openddlparser/code/OpenDDLExport.cpp ../contrib/openddlparser/code/Value.cpp ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h + ../contrib/openddlparser/include/openddlparser/OpenDDLExport.h ../contrib/openddlparser/include/openddlparser/DDLNode.h ../contrib/openddlparser/include/openddlparser/Value.h ) diff --git a/contrib/openddlparser/code/DDLNode.cpp b/contrib/openddlparser/code/DDLNode.cpp index 5d3fd03f9..d5ff20482 100644 --- a/contrib/openddlparser/code/DDLNode.cpp +++ b/contrib/openddlparser/code/DDLNode.cpp @@ -49,11 +49,7 @@ static void releaseReferencedNames( Reference *ref ) { return; } - if( ref->m_referencedName ) { - for( size_t i = 0; i < ref->m_numRefs; i++ ) { - delete ref->m_referencedName; - } - } + delete ref; } DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent ) @@ -143,6 +139,10 @@ bool DDLNode::hasProperty( const std::string &name ) { return ( ddl_nullptr != prop ); } +bool DDLNode::hasProperties() const { + return( ddl_nullptr != m_properties ); +} + Property *DDLNode::findPropertyByName( const std::string &name ) { if( name.empty() ) { return ddl_nullptr; diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp index 77a1c4a25..5505f78b5 100644 --- a/contrib/openddlparser/code/OpenDDLParser.cpp +++ b/contrib/openddlparser/code/OpenDDLParser.cpp @@ -36,17 +36,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN_ODDLPARSER_NS -static const char *Version = "0.1.0"; +static const char *Version = "0.3.0"; namespace Grammar { - static const char * const OpenBracketToken = "{"; - static const char * const CloseBracketToken = "}"; - static const char * const OpenPropertyToken = "("; - static const char * const ClosePropertyToken = ")"; - static const char * const BoolTrue = "true"; - static const char * const BoolFalse = "false"; - static const char * const RefToken = "ref"; - static const char * const CommaSeparator = ","; + static const char *OpenBracketToken = "{"; + static const char *CloseBracketToken = "}"; + static const char *OpenPropertyToken = "("; + static const char *ClosePropertyToken = ")"; + static const char *OpenArrayToken = "["; + static const char *CloseArrayToken = "]"; + static const char *BoolTrue = "true"; + static const char *BoolFalse = "false"; + static const char *CommaSeparator = ","; static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = { "bool", @@ -66,7 +67,6 @@ namespace Grammar { }; } // Namespace Grammar - static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) { std::stringstream stream; stream << "Invalid token " << *in << ", " << exp << " expected." << std::endl; @@ -206,6 +206,18 @@ bool OpenDDLParser::parse() { return true; } +bool OpenDDLParser::exportContext( Context *ctx, const std::string &filename ) { + if( ddl_nullptr == ctx ) { + return false; + } + + if( filename.empty() ) { + return false; + } + return false; +} + + char *OpenDDLParser::parseNextNode( char *in, char *end ) { in = parseHeader( in, end ); in = parseStructure( in, end ); @@ -234,19 +246,19 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) { in = lookForNextToken( in, end ); Property *first( ddl_nullptr ); if( ddl_nullptr != id ) { - if( *in == '(' ) { + if( *in == Grammar::OpenPropertyToken[ 0 ] ) { in++; Property *prop( ddl_nullptr ), *prev( ddl_nullptr ); - while( *in != ')' && in != end ) { + while( *in != Grammar::ClosePropertyToken[ 0 ] && in != end ) { in = OpenDDLParser::parseProperty( in, end, &prop ); in = lookForNextToken( in, end ); - if( *in != ',' && *in != ')' ) { - logInvalidTokenError( in, ")", m_logCallback ); + if( *in != Grammar::CommaSeparator[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] ) { + logInvalidTokenError( in, Grammar::ClosePropertyToken, m_logCallback ); return in; } - if( ddl_nullptr != prop && *in != ',' ) { + if( ddl_nullptr != prop && *in != Grammar::CommaSeparator[ 0 ] ) { if( ddl_nullptr == first ) { first = prop; } @@ -348,7 +360,7 @@ char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) { if( Value::ddl_none != type ) { // parse a primitive data type in = lookForNextToken( in, end ); - if( *in == '{' ) { + if( *in == Grammar::OpenBracketToken[ 0 ] ) { Reference *refs( ddl_nullptr ); DataArrayList *dtArrayList( ddl_nullptr ); Value *values( ddl_nullptr ); @@ -435,10 +447,10 @@ void OpenDDLParser::normalizeBuffer( std::vector &buffer) { newBuffer.push_back( buffer[ readIdx ] ); } else { if( isComment( c, end ) ) { - readIdx++; + ++readIdx; // skip the comment and the rest of the line while( !isEndofLine( buffer[ readIdx ] ) ) { - readIdx++; + ++readIdx; } } } @@ -493,9 +505,9 @@ char *OpenDDLParser::parseIdentifier( char *in, char *end, Identifier **id ) { // get size of id size_t idLen( 0 ); char *start( in ); - while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != '(' && *in != ')' ) { - in++; - idLen++; + while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != Grammar::OpenPropertyToken[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] ) { + ++in; + ++idLen; } const size_t len( idLen ); @@ -529,13 +541,13 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy } bool ok( true ); - if( *in == '[' ) { + if( *in == Grammar::OpenArrayToken[ 0 ] ) { ok = false; in++; char *start( in ); while ( in != end ) { in++; - if( *in == ']' ) { + if( *in == Grammar::CloseArrayToken[ 0 ] ) { len = atoi( start ); ok = true; in++; @@ -562,9 +574,9 @@ char *OpenDDLParser::parseReference( char *in, char *end, std::vector &na if( nextName ) { names.push_back( nextName ); } - while( ',' == *in ) { + while( Grammar::CommaSeparator[ 0 ] == *in ) { in = getNextSeparator( in, end ); - if( ',' == *in ) { + if( Grammar::CommaSeparator[ 0 ] == *in ) { in = parseName( in, end, &nextName ); if( nextName ) { names.push_back( nextName ); @@ -846,7 +858,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value **data, size_t &n } in = getNextSeparator( in, end ); - if( ',' != *in && '}' != *in && !isSpace( *in ) ) { + if( ',' != *in && Grammar::CloseBracketToken[ 0 ] != *in && !isSpace( *in ) ) { break; } } diff --git a/contrib/openddlparser/code/Value.cpp b/contrib/openddlparser/code/Value.cpp index 78ae00c92..52081cea5 100644 --- a/contrib/openddlparser/code/Value.cpp +++ b/contrib/openddlparser/code/Value.cpp @@ -27,6 +27,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN_ODDLPARSER_NS +static Value::Iterator end( ddl_nullptr ); + Value::Iterator::Iterator() : m_start( ddl_nullptr ) , m_current( ddl_nullptr ) { @@ -39,6 +41,12 @@ Value::Iterator::Iterator( Value *start ) // empty } +Value::Iterator::Iterator( const Iterator &rhs ) +: m_start( rhs.m_start ) +, m_current( rhs.m_current ) { + // empty +} + Value::Iterator::~Iterator() { // empty } @@ -61,6 +69,38 @@ Value *Value::Iterator::getNext() { return v; } +const Value::Iterator Value::Iterator::operator++( int ) { + if( ddl_nullptr == m_current ) { + return end; + } + + m_current = m_current->getNext(); + Iterator inst( m_current ); + + return inst; +} + +Value::Iterator &Value::Iterator::operator++( ) { + if( ddl_nullptr == m_current ) { + return end; + } + + m_current = m_current->getNext(); + + return *this; +} + +bool Value::Iterator::operator == ( const Iterator &rhs ) const { + return ( m_current == rhs.m_current ); +} + +Value *Value::Iterator::operator->( ) const { + if( nullptr == m_current ) { + return ddl_nullptr; + } + return m_current; +} + Value::Value( ValueType type ) : m_type( type ) , m_size( 0 ) @@ -80,7 +120,8 @@ void Value::setBool( bool value ) { bool Value::getBool() { assert( ddl_bool == m_type ); - return ( *m_data ) ? true : false; + + return ( *m_data == 1 ); } void Value::setInt8( int8 value ) { diff --git a/contrib/openddlparser/include/openddlparser/DDLNode.h b/contrib/openddlparser/include/openddlparser/DDLNode.h index 8fce95f53..8cef469d0 100644 --- a/contrib/openddlparser/include/openddlparser/DDLNode.h +++ b/contrib/openddlparser/include/openddlparser/DDLNode.h @@ -101,6 +101,10 @@ public: /// @return true, if a corresponding property is assigned to the node, false if not. bool hasProperty( const std::string &name ); + /// @brief Will return true, if any properties are assigned to the node instance. + /// @return True, if properties are assigned. + bool hasProperties() const; + /// @brief Search for a given property and returns it. Will return ddl_nullptr if no property was found. /// @param name [in] The name for the property to look for. /// @return The property or ddl_nullptr if no property was found. diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h index e5fe77777..c86c7ce9d 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h @@ -56,10 +56,11 @@ BEGIN_ODDLPARSER_NS // All C++11 constructs # define ddl_nullptr nullptr #else - // Fallback for older compilers + // Fall-back for older compilers # define ddl_nullptr NULL #endif // OPENDDL_NO_USE_CPP11 +// Forward declarations class DDLNode; class Value; @@ -69,6 +70,7 @@ struct Reference; struct Property; struct DataArrayList; +// Platform-specific typedefs #ifdef _WIN32 typedef signed __int64 int64_impl; typedef unsigned __int64 uint64_impl; @@ -87,65 +89,36 @@ typedef unsigned short uint16; ///< Unsigned integer, 2 byte typedef unsigned int uint32; ///< Unsigned integer, 4 byte typedef uint64_impl uint64; ///< Unsigned integer, 8 byte -/// @brief Description of the type of a name. -enum NameType { - GlobalName, ///< Name is global. - LocalName ///< Name is local. -}; +/// @brief Stores a text. +/// +/// A text is stored in a simple character buffer. Texts buffer can be +/// greater than the number of stored characters in them. +struct DLL_ODDLPARSER_EXPORT Text { + size_t m_capacity; ///< The capacity of the text. + size_t m_len; ///< The length of the text. + char *m_buffer; ///< The buffer with the text. -/// @brief Stores a text -struct Text { - size_t m_capacity; - size_t m_len; - char *m_buffer; + /// @brief The constructor with a given text buffer. + /// @param buffer [in] The buffer. + /// @param numChars [in] The number of characters in the buffer. + Text( const char *buffer, size_t numChars ); - Text( const char *buffer, size_t numChars ) - : m_capacity( 0 ) - , m_len( 0 ) - , m_buffer( ddl_nullptr ) { - set( buffer, numChars ); - } + /// @brief The destructor. + ~Text(); - ~Text() { - clear(); - } + /// @brief Clears the text. + void clear(); - void clear() { - delete[] m_buffer; - m_buffer = ddl_nullptr; - m_capacity = 0; - m_len = 0; - } + /// @brief Set a new text. + /// @param buffer [in] The buffer. + /// @param numChars [in] The number of characters in the buffer. + void set( const char *buffer, size_t numChars ); - void set( const char *buffer, size_t numChars ) { - clear(); - if( numChars > 0 ) { - m_len = numChars; - m_capacity = m_len + 1; - m_buffer = new char[ m_capacity ]; - strncpy( m_buffer, buffer, numChars ); - m_buffer[ numChars ] = '\0'; - } - } + /// @brief The compare operator for std::strings. + bool operator == ( const std::string &name ) const; - bool operator == ( const std::string &name ) const { - if( m_len != name.size() ) { - return false; - } - const int res( strncmp( m_buffer, name.c_str(), name.size() ) ); - - return ( 0 == res ); - } - - bool operator == ( const Text &rhs ) const { - if( m_len != rhs.m_len ) { - return false; - } - - const int res( strncmp( m_buffer, rhs.m_buffer, m_len ) ); - - return ( 0 == res ); - } + /// @brief The compare operator for Texts. + bool operator == ( const Text &rhs ) const; private: Text( const Text & ); @@ -153,38 +126,48 @@ private: }; /// @brief Stores an OpenDDL-specific identifier type. -struct Identifier { - Text m_text; +struct DLL_ODDLPARSER_EXPORT Identifier { + Text m_text; ///< The text element. - Identifier( char buffer[], size_t len ) - : m_text( buffer, len ) { - // empty - } + /// @brief The constructor with a sized buffer full of characters. + /// @param buffer [in] The identifier buffer. + /// @param len [in] The length of the buffer + Identifier( const char buffer[], size_t len ); - Identifier( char buffer[] ) - : m_text( buffer, strlen( buffer ) ) { - // empty - } + /// @brief The constructor with a buffer full of characters. + /// @param buffer [in] The identifier buffer. + /// @remark Buffer must be null-terminated. + Identifier( const char buffer[] ); - bool operator == ( const Identifier &rhs ) const { - return m_text == rhs.m_text; - } + /// @brief The destructor. + ~Identifier(); + + /// @brief The compare operator. + bool operator == ( const Identifier &rhs ) const; private: Identifier( const Identifier & ); Identifier &operator = ( const Identifier & ); }; -/// @brief Stores an OpenDDL-specific name -struct Name { - NameType m_type; - Identifier *m_id; +/// @brief Description of the type of a name. +enum NameType { + GlobalName, ///< Name is global. + LocalName ///< Name is local. +}; - Name( NameType type, Identifier *id ) - : m_type( type ) - , m_id( id ) { - // empty - } +/// @brief Stores an OpenDDL-specific name +struct DLL_ODDLPARSER_EXPORT Name { + NameType m_type; ///< The type of the name ( @see NameType ). + Identifier *m_id; ///< The id. + + /// @brief The constructor with the type and the id. + /// @param type [in] The name type. + /// @param id [in] The id. + Name( NameType type, Identifier *id ); + + /// @brief The destructor. + ~Name(); private: Name( const Name & ); @@ -192,33 +175,20 @@ private: }; /// @brief Stores a bundle of references. -struct Reference { - size_t m_numRefs; - Name **m_referencedName; +struct DLL_ODDLPARSER_EXPORT Reference { + size_t m_numRefs; ///< The number of stored references. + Name **m_referencedName; ///< The reference names. - Reference() - : m_numRefs( 0 ) - , m_referencedName( ddl_nullptr ) { - // empty - } + /// @brief The default constructor. + Reference(); - Reference( size_t numrefs, Name **names ) - : m_numRefs( numrefs ) - , m_referencedName( ddl_nullptr ) { - m_referencedName = new Name *[ numrefs ]; - for( size_t i = 0; i < numrefs; i++ ) { - Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id ); - m_referencedName[ i ] = name; - } - } + /// @brief The constructor with an array of ref names. + /// @param numrefs [in] The number of ref names. + /// @param names [in] The ref names. + Reference( size_t numrefs, Name **names ); - ~Reference() { - for( size_t i = 0; i < m_numRefs; i++ ) { - delete m_referencedName[ i ]; - } - m_numRefs = 0; - m_referencedName = ddl_nullptr; - } + /// @brief The destructor. + ~Reference(); private: Reference( const Reference & ); @@ -226,26 +196,21 @@ private: }; /// @brief Stores a property list. -struct Property { - Identifier *m_key; - Value *m_value; - Reference *m_ref; - Property *m_next; +struct DLL_ODDLPARSER_EXPORT Property { + Identifier *m_key; ///< The identifier / key of the property. + Value *m_value; ///< The value assigned to its key / id ( ddl_nullptr if none ). + Reference *m_ref; ///< References assigned to its key / id ( ddl_nullptr if none ). + Property *m_next; ///< The next property ( ddl_nullptr if none ). - Property( Identifier *id ) - : m_key( id ) - , m_value( ddl_nullptr ) - , m_ref( ddl_nullptr ) - , m_next( ddl_nullptr ) { - // empty - } + /// @brief The default constructor. + Property(); - ~Property() { - m_key = ddl_nullptr; - m_value = ddl_nullptr; - m_ref = ddl_nullptr;; - m_next = ddl_nullptr;; - } + /// @brief The constructor for initialization. + /// @param id [in] The identifier + Property( Identifier *id ); + + /// @brief The destructor. + ~Property(); private: Property( const Property & ); @@ -253,17 +218,16 @@ private: }; /// @brief Stores a data array list. -struct DataArrayList { - size_t m_numItems; - Value *m_dataList; - DataArrayList *m_next; +struct DLL_ODDLPARSER_EXPORT DataArrayList { + size_t m_numItems; ///< The number of items in the list. + Value *m_dataList; ///< The data list ( ee Value ). + DataArrayList *m_next; ///< The next data array list ( ddl_nullptr if last ). - DataArrayList() - : m_numItems( 0 ) - , m_dataList( ddl_nullptr ) - , m_next( ddl_nullptr ) { - // empty - } + /// @brief The default constructor for initialization. + DataArrayList(); + + /// @brief The destructor. + ~DataArrayList(); private: DataArrayList( const DataArrayList & ); @@ -271,17 +235,17 @@ private: }; /// @brief Stores the context of a parsed OpenDDL declaration. -struct Context { - DDLNode *m_root; +struct DLL_ODDLPARSER_EXPORT Context { + DDLNode *m_root; ///< The root node of the OpenDDL node tree. - Context() - : m_root( ddl_nullptr ) { - // empty - } + /// @brief Constructor for initialization. + Context(); - ~Context() { - m_root = ddl_nullptr; - } + /// @brief Destructor. + ~Context(); + + /// @brief Clears the whole node tree. + void clear(); private: Context( const Context & ); diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParser.h b/contrib/openddlparser/include/openddlparser/OpenDDLParser.h index 607dcf90c..5c33895b6 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLParser.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLParser.h @@ -39,6 +39,11 @@ struct Identifier; struct Reference; struct Property; +/// @brief Utility function to search for the next token or the end of the buffer. +/// @param in [in] The start position in the buffer. +/// @param end [in] The end position in the buffer. +/// @return Pointer showing to the next token or the end of the buffer. +/// @detail Will not increase buffer when already a valid buffer was found. template inline T *lookForNextToken( T *in, T *end ) { @@ -48,13 +53,19 @@ T *lookForNextToken( T *in, T *end ) { return in; } +/// @brief Utility function to go for the next token or the end of the buffer. +/// @param in [in] The start position in the buffer. +/// @param end [in] The end position in the buffer. +/// @return Pointer showing to the next token or the end of the buffer. +/// @detail Will increase buffer by a minimum of one. template inline T *getNextToken( T *in, T *end ) { T *tmp( in ); - while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) { + in = lookForNextToken( in, end ); + /*while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) { in++; - } + }*/ if( tmp == in ) { in++; } @@ -69,22 +80,76 @@ enum LogSeverity { ddl_error_msg ///< Parser errors }; +//------------------------------------------------------------------------------------------------- +/// @class OpenDDLParser +/// @ingroup OpenDDLParser + +/// +/// @brief This is the main API for the OpenDDL-parser. +/// +/// Use instances of this class to manage the parsing and handling of your parser contexts. +//------------------------------------------------------------------------------------------------- class DLL_ODDLPARSER_EXPORT OpenDDLParser { public: + /// @brief The log callback function pointer. typedef void( *logCallback )( LogSeverity severity, const std::string &msg ); public: + /// @brief The default class constructor. OpenDDLParser(); + + /// @brief The class constructor. + /// @param buffer [in] The buffer + /// @param len [in] Size of the buffer OpenDDLParser( char *buffer, size_t len ); + + /// @brief The class destructor. ~OpenDDLParser(); + + /// @brief Setter for an own log callback function. + /// @param callback [in] The own callback. void setLogCallback( logCallback callback ); + + /// @brief Getter for the log callback. + /// @return The current log callback. logCallback getLogCallback() const; + + /// @brief Assigns a new buffer to parse. + /// @param buffer [in] The buffer + /// @param len [in] Size of the buffer void setBuffer( char *buffer, size_t len ); + + /// @brief Assigns a new buffer to parse. + /// @param buffer [in] The buffer as a std::vector. void setBuffer( const std::vector &buffer ); + + /// @brief Returns the buffer pointer. + /// @return The buffer pointer. const char *getBuffer() const; + + /// @brief Returns the size of the buffer. + /// @return The buffer size. size_t getBufferSize() const; + + /// @brief Clears all parser data, including buffer and active context. void clear(); + + /// @brief Starts the parsing of the OpenDDL-file. + /// @return True in case of success, false in case of an error. + /// @remark In case of errors check log. bool parse(); + + bool exportContext( Context *ctx, const std::string &filename ); + + /// @brief Returns the root node. + /// @return The root node. + DDLNode *getRoot() const; + + /// @brief Returns the parser context, only available in case of a succeeded parsing. + /// @return Pointer to the active context or ddl_nullptr. + Context *getContext() const; + +public: // parser helpers char *parseNextNode( char *current, char *end ); char *parseHeader( char *in, char *end ); char *parseStructure( char *in, char *end ); @@ -92,10 +157,6 @@ public: void pushNode( DDLNode *node ); DDLNode *popNode(); DDLNode *top(); - DDLNode *getRoot() const; - Context *getContext() const; - -public: // static parser helpers static void normalizeBuffer( std::vector &buffer ); static char *parseName( char *in, char *end, Name **name ); static char *parseIdentifier( char *in, char *end, Identifier **id ); diff --git a/contrib/openddlparser/include/openddlparser/Value.h b/contrib/openddlparser/include/openddlparser/Value.h index fc8cc1ee1..00b644540 100644 --- a/contrib/openddlparser/include/openddlparser/Value.h +++ b/contrib/openddlparser/include/openddlparser/Value.h @@ -61,6 +61,8 @@ public: /// @param start [in] The first value for iteration, Iterator( Value *start ); + Iterator( const Iterator &rhs ); + /// @brief The class destructor. ~Iterator(); @@ -71,13 +73,27 @@ public: /// @brief Returns the next item and moves the iterator to it. /// @return The next value, is ddl_nullptr in case of being the last item. Value *getNext(); + + /// @brief The post-increment operator. + const Iterator operator++( int ); + + /// @brief The pre-increment operator. + Iterator &operator++( ); + + /// @brief The compare operator. + /// @param rhs [in] The instance to compare. + /// @return true if equal. + bool operator == ( const Iterator &rhs ) const; + + /// @brief The * operator. + /// @return The instance or ddl_nullptr if end of list is reached. + Value *operator->( ) const; private: Value *m_start; Value *m_current; private: - Iterator( const Iterator & ); Iterator &operator = ( const Iterator & ); }; diff --git a/include/assimp/material.h b/include/assimp/material.h index e4d4565db..f21a77c41 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -735,7 +735,7 @@ public: C_STRUCT aiString* path, aiTextureMapping* mapping = NULL, unsigned int* uvindex = NULL, - float* blend = NULL, + float* blend = NULL, aiTextureOp* op = NULL, aiTextureMapMode* mapmode = NULL) const; @@ -1344,9 +1344,9 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialProperty( * arrays remains unmodified and pMax is set to 0.*/ // --------------------------------------------------------------------------- ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray( - const C_STRUCT aiMaterial* pMat, + const C_STRUCT aiMaterial* pMat, const char* pKey, - unsigned int type, + unsigned int type, unsigned int index, float* pOut, unsigned int* pMax); @@ -1376,7 +1376,7 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray( inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat, const char* pKey, unsigned int type, - unsigned int index, + unsigned int index, float* pOut) { return aiGetMaterialFloatArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0); @@ -1397,11 +1397,11 @@ inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat, * * See the sample for aiGetMaterialFloatArray for more information.*/ ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat, - const char* pKey, + const char* pKey, unsigned int type, unsigned int index, - int* pOut, - unsigned int* pMax); + int* pOut, + unsigned int* pMax); #ifdef __cplusplus @@ -1437,9 +1437,9 @@ inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat, // --------------------------------------------------------------------------- ASSIMP_API C_ENUM aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, const char* pKey, - unsigned int type, + unsigned int type, unsigned int index, - C_STRUCT aiColor4D* pOut); + C_STRUCT aiColor4D* pOut); // --------------------------------------------------------------------------- @@ -1449,9 +1449,9 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, // --------------------------------------------------------------------------- ASSIMP_API C_ENUM aiReturn aiGetMaterialUVTransform(const C_STRUCT aiMaterial* pMat, const char* pKey, - unsigned int type, + unsigned int type, unsigned int index, - C_STRUCT aiUVTransform* pOut); + C_STRUCT aiUVTransform* pOut); // --------------------------------------------------------------------------- @@ -1461,7 +1461,7 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialUVTransform(const C_STRUCT aiMaterial* p // --------------------------------------------------------------------------- ASSIMP_API C_ENUM aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat, const char* pKey, - unsigned int type, + unsigned int type, unsigned int index, C_STRUCT aiString* pOut); diff --git a/test/unit/utRemoveComments.cpp b/test/unit/utRemoveComments.cpp index f0977f374..611658e8a 100644 --- a/test/unit/utRemoveComments.cpp +++ b/test/unit/utRemoveComments.cpp @@ -15,9 +15,9 @@ TEST(RemoveCommentsTest, testSingleLineComments) "\ttrue) { // do something here \n" "\t// hello ... and bye //\n"; - - char* szTest2 = new char[::strlen(szTest)+1]; - ::strcpy(szTest2,szTest); + const size_t len( ::strlen( szTest ) + 1 ); + char* szTest2 = new char[ len ]; + ::strncpy( szTest2, szTest, len ); const char* szTestResult = "int i = 0; \n" "if (4 == \n" @@ -45,8 +45,9 @@ TEST(RemoveCommentsTest, testMultiLineComments) " " " / * Incomplete comment */ */"; - char* szTest2 = new char[::strlen(szTest)+1]; - ::strcpy(szTest2,szTest); + const size_t len( ::strlen( szTest ) + 1 ); + char* szTest2 = new char[ len ]; + ::strncpy( szTest2, szTest, len ); CommentRemover::RemoveMultiLineComments("/*","*/",szTest2,' '); EXPECT_STREQ(szTestResult, szTest2); From e7fa8fa8aec0aa7b784b3f90cfe5554ee5774a2f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 2 Oct 2015 00:38:50 +0200 Subject: [PATCH 19/77] OpenDDLParser: add missing files. --- contrib/openddlparser/code/OpenDDLCommon.cpp | 168 ++++++++++++++++++ contrib/openddlparser/code/OpenDDLExport.cpp | 116 ++++++++++++ .../include/openddlparser/OpenDDLExport.h | 48 +++++ 3 files changed, 332 insertions(+) create mode 100644 contrib/openddlparser/code/OpenDDLCommon.cpp create mode 100644 contrib/openddlparser/code/OpenDDLExport.cpp create mode 100644 contrib/openddlparser/include/openddlparser/OpenDDLExport.h diff --git a/contrib/openddlparser/code/OpenDDLCommon.cpp b/contrib/openddlparser/code/OpenDDLCommon.cpp new file mode 100644 index 000000000..00583a101 --- /dev/null +++ b/contrib/openddlparser/code/OpenDDLCommon.cpp @@ -0,0 +1,168 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#include +#include + +BEGIN_ODDLPARSER_NS + +Text::Text( const char *buffer, size_t numChars ) +: m_capacity( 0 ) +, m_len( 0 ) +, m_buffer( ddl_nullptr ) { + set( buffer, numChars ); +} + +Text::~Text() { + clear(); +} + +void Text::clear() { + delete[] m_buffer; + m_buffer = ddl_nullptr; + m_capacity = 0; + m_len = 0; +} + +void Text::set( const char *buffer, size_t numChars ) { + clear(); + if( numChars > 0 ) { + m_len = numChars; + m_capacity = m_len + 1; + m_buffer = new char[ m_capacity ]; + strncpy( m_buffer, buffer, numChars ); + m_buffer[ numChars ] = '\0'; + } +} + +bool Text::operator == ( const std::string &name ) const { + if( m_len != name.size() ) { + return false; + } + const int res( strncmp( m_buffer, name.c_str(), name.size() ) ); + + return ( 0 == res ); +} + +bool Text::operator == ( const Text &rhs ) const { + if( m_len != rhs.m_len ) { + return false; + } + + const int res( strncmp( m_buffer, rhs.m_buffer, m_len ) ); + + return ( 0 == res ); +} + +Identifier::Identifier( const char buffer[], size_t len ) +: m_text( buffer, len ) { + // empty +} + +Identifier::Identifier( const char buffer[] ) +: m_text( buffer, strlen( buffer ) ) { + // empty +} + +Identifier::~Identifier() { + // empty +} + +bool Identifier::operator == ( const Identifier &rhs ) const { + return m_text == rhs.m_text; +} + +Name::Name( NameType type, Identifier *id ) +: m_type( type ) +, m_id( id ) { + // empty +} + +Name::~Name() { + m_id = ddl_nullptr; +} + +Reference::Reference() +: m_numRefs( 0 ) +, m_referencedName( ddl_nullptr ) { + // empty +} + +Reference::Reference( size_t numrefs, Name **names ) +: m_numRefs( numrefs ) +, m_referencedName( ddl_nullptr ) { + m_referencedName = new Name *[ numrefs ]; + for( size_t i = 0; i < numrefs; i++ ) { + Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id ); + m_referencedName[ i ] = name; + } +} + +Reference::~Reference() { + for( size_t i = 0; i < m_numRefs; i++ ) { + delete m_referencedName[ i ]; + } + m_numRefs = 0; + m_referencedName = ddl_nullptr; +} + +Property::Property( Identifier *id ) +: m_key( id ) +, m_value( ddl_nullptr ) +, m_ref( ddl_nullptr ) +, m_next( ddl_nullptr ) { + // empty +} + +Property::~Property() { + m_key = ddl_nullptr; + m_value = ddl_nullptr; + m_ref = ddl_nullptr;; + m_next = ddl_nullptr;; +} + +DataArrayList::DataArrayList() +: m_numItems( 0 ) +, m_dataList( ddl_nullptr ) +, m_next( ddl_nullptr ) { + // empty +} + +DataArrayList::~DataArrayList() { + // empty +} + +Context::Context() +: m_root( ddl_nullptr ) { + // empty +} + +Context::~Context() { + m_root = ddl_nullptr; +} + +void Context::clear() { + delete m_root; + m_root = ddl_nullptr; +} + +END_ODDLPARSER_NS diff --git a/contrib/openddlparser/code/OpenDDLExport.cpp b/contrib/openddlparser/code/OpenDDLExport.cpp new file mode 100644 index 000000000..5a010ea59 --- /dev/null +++ b/contrib/openddlparser/code/OpenDDLExport.cpp @@ -0,0 +1,116 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#include +#include + +BEGIN_ODDLPARSER_NS + +struct DDLNodeIterator { + const DDLNode::DllNodeList &m_childs; + size_t m_idx; + DDLNodeIterator( const DDLNode::DllNodeList &childs ) + : m_childs( childs ) + , m_idx( 0 ) { + + } + + bool getNext( DDLNode **node ) { + if( m_childs.size() > (m_idx+1) ) { + m_idx++; + *node = m_childs[ m_idx ]; + return true; + } + + return false; + } +}; + +OpenDDLExport::OpenDDLExport() +:m_file( nullptr ) { + +} + +OpenDDLExport::~OpenDDLExport() { + if( nullptr != m_file ) { + ::fclose( m_file ); + m_file = nullptr; + } +} + +bool OpenDDLExport::exportContext( Context *ctx, const std::string &filename ) { + if( filename.empty() ) { + return false; + } + + if( ddl_nullptr == ctx ) { + return false; + } + + DDLNode *root( ctx->m_root ); + if( nullptr == root ) { + return true; + } + + return handleNode( root ); +} + +bool OpenDDLExport::handleNode( DDLNode *node ) { + if( ddl_nullptr == node ) { + return true; + } + + const DDLNode::DllNodeList &childs = node->getChildNodeList(); + if( childs.empty() ) { + return true; + } + DDLNode *current( ddl_nullptr ); + DDLNodeIterator it( childs ); + bool success( true ); + while( it.getNext( ¤t ) ) { + if( ddl_nullptr != current ) { + success |= writeNode( current ); + if( !handleNode( current ) ) { + success != false; + } + } + } + + return success; +} + +bool OpenDDLExport::writeNode( DDLNode *node ) { + bool success( true ); + if( node->hasProperties() ) { + success |= writeProperties( node ); + } + + return true; +} + +bool OpenDDLExport::writeProperties( DDLNode *node ) { + Property *prop( node->getProperties() ); + + return true; +} + +END_ODDLPARSER_NS diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLExport.h b/contrib/openddlparser/include/openddlparser/OpenDDLExport.h new file mode 100644 index 000000000..269296527 --- /dev/null +++ b/contrib/openddlparser/include/openddlparser/OpenDDLExport.h @@ -0,0 +1,48 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#pragma once + +#include + +BEGIN_ODDLPARSER_NS + +/// +/// @ingroup OpenDDLParser +/// @brief This class represents the OpenDDLExporter. +/// +class DLL_ODDLPARSER_EXPORT OpenDDLExport { +public: + OpenDDLExport(); + ~OpenDDLExport(); + bool exportContext( Context *ctx, const std::string &filename ); + bool handleNode( DDLNode *node ); + +protected: + bool writeNode( DDLNode *node ); + bool writeProperties( DDLNode *node ); + +private: + FILE *m_file; +}; + +END_ODDLPARSER_NS From b5be5a64f701fcc35bad8ac25f79371a34258176 Mon Sep 17 00:00:00 2001 From: Alexander Gessler Date: Tue, 6 Oct 2015 17:51:23 +0200 Subject: [PATCH 20/77] Let appveyor decide on OS version, hopefully fixes appveyor failure. --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 6e5c146a1..8c3264cbf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,6 @@ # AppVeyor file # http://www.appveyor.com/docs/appveyor-yml -# Operating system (build VM template) -os: Previous Windows Server 2012 R2 # using previous worker images since default worker has problem installing DART-Prerequisites.msi - # clone directory clone_folder: c:\projects\assimp From 1a1fd897b6d3b40a0b2435a369aced165f59d8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= Date: Wed, 7 Oct 2015 17:02:48 +0300 Subject: [PATCH 21/77] Updated regression test database for MD5 files --- test/regression/db.zip | Bin 1475372 -> 1475266 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/regression/db.zip b/test/regression/db.zip index 3808ded597b5c3a59ca15644d79325fbee5f0b23..c94598840c94ccdbb7d8c4f67cd5d7c292c4a489 100644 GIT binary patch delta 139038 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]Xc-#0EThNDXToOdqhHYe`KA@~)Qn+;&YH9hZ;80L1c2o{8GRFfw{ z0>H6y$A2m+OIF=6Td9(4cB?)%?5KHlS!|?2T=;fYVD^-lqjX1CV;S`Bu-)`b@z?lb zlvlIR6U{Xlm2#mC%EDshIMYhJeL8&R8H^kM6^eHq0IqxM@V-$)Bj_q&RbZe$w?hi5 zz{MIG6aaq#{5%{KrG^-!%?I=%#Q;S7wF`6UGq`CxF^#8W8zx9U3y8zwdd(R`Zr+)T z=>G97&JKgn_fcn_Akmt=B3_U(eUB6^+1=Pl&KBWfi5A@dayTp1Wb1+ZBc2|>hxERbpKK0`E4$5BaEq=jvd|<%>xl;a%urB!1ElB%s;OH z3G~?{T>KMnag5hUP4gWfvGDxrr)-^(Qg5vW|5cv-;}S)WRQk^fOv}vRcKa2B zq~p*QB|4ZV)z@K2M*K^)Vt9?atm0L`sEAIgo%r4e|4AI%XG+6Qa}KG3o;1(B1NyN7 z1!rz&f}6*R&g}&qLK8$k8or(6@s}5h8My|E4O~6exfm=PVcsV(RsYdk!-w}&M15;C znQR{rPy71~D@Jp+a{y6-SbSc6gw5nPe8irUn0knNE(Xf-xTEnDnmKVun#{l&;5UpX zcL(;+TJpAF*=(`Mr*S>dPRIL3NAAa*JiYBfSoLnkyx)W}8qSU?@!xBP*fp-Epopq} z91uMi?oJmwzXgxeGIapthGH;>UWB`F>qo$lB}N1QJG~TCSNn~RU$?r~G**S!rCL~B zmB!vFfGd@|$fGo*Zk8%up^(MSfX!C61#MhKro$g;4AHS$8a39Er`O%aClkiIx$_5J z24kI>s-2b_!zvznM2=;_(?t24{$h=iQwyGXpVho_eo#RkK`;D@OEH@3@LQDVe1=o^-l;&Mc~kawV~sLO{wYkC*Dr0wRVGYigj( zD0jUmsmiIW?&wZX-M@ZkA1OJ>jP=^6&@%pOSMMf*cI6mKF+50V6=w8_bl^AIj~FzQ zB|0-nQ5zl6bWMZ^s^M}*RsmX8{rIX5j>5H_?-i1nVmzxo7{Bir_g3<-&aTfeX@fmjypXtuUv83#h z)7NjPRfEx57(VlTp}r%k7sGxg8_do}Z(;ZnOyCPu$JH|B!3(ABAPlg2w1_s#Thim? z7hP9TB*X_Fg2J)F7LmE=aS>bFtdb#*&+Abw$F;?fS{Rwmp1_f$uKeZ0E^(Fn6W8EW zjlJ_$@)!n>hO|0*L#Gs$~|hUa?Yw|>R3&MLnGeTa9zM@ z(qEjCL5}^|#D#ugzDCs4z>ycTsL}ytT-UtC6Qn4zAH|#ezgKJ!ew7aC;}c(K=(yqz zkc{0*+rFP&ajXW-r65O^)PYrCP@8>RAVSkcM(0@<{X}f_JOHn$*BtJV!kF->)>Fvg zq|`?A%YRo_n?_AnK3%!YGlZ>s5nfS&2Di6r2>hDQ`AyJU)XhKRwAYp=n>JK*q3c$_aXrYcOBLwSjrtS9%93em?+iULkV*&c>H2>`gQ9Fsuv-DyqyZ zX~;56uk;VJ^`-FVQ@=+u!5n$h+C2xQ?yw%74yhcWx4~0<)Vxz|wNDY+WKDeW1KwXq z#agtD1B32-QX>5ZlF|R(=9C^B=w(qVLD>fk7F%Vp@MlX*-Le<% z>S(j~@r!2z20pt6_=>&6fGgVv22qX5Q3|!+?-~qTo0B?pw}Rq%KH;+s4x_nh=aHwl zjtg0H{^-!}7Ff;yEvE6tE5b2;`hKa|iD9IxA*)MA06Ee5>nc+}W8)s#qW{i)C;a9% zo{oRA1gMEqa{aj#{KOW1G+1uo+bK}=ZOv0u)r41t5aAORUkHIvU2gZjF4s*&RQ+;x zV+zy;$ued!Yp;V#3)^W~x)uGHW|12L8lx0Kd-?C3W77jOBXvTAmIFhoq{4u;j>@`` z*#N#J>u(#aBjQ)?X^7!wj0aB{KW)Fgso)pX>H&^${NchJ#mczjGmyz9@*Te4t#nwq zE`u9AgJ_oZ3&*(Uii8raNtt0xlRCQ9%(^hFyh-nW`x(wh>c^X9&?;g(lOTEZQf$zJ zFJI`FqIP(+vV3@*|Fy~X+&S*futQ?`Oy6$(FdeH_VyTXqglOA!bf(OXf^&VnR^c&` z&KL0gRs^n-Op_tTL$GQ}ATDDn&TIW^9PI*y%5p$Mju}hXu~ETZd4R+^vNf4a^+sX4 z<;`67#+)UDw-=fy!Wm0K4#!KnhlWk%3Sq_699(I~tY++o=zur^2* zLC~UZIIYTmWWf9k30RUu=iC?q}G>YVJ>90Wr}8c@;=d*?=`^ zP;K_IcrX3tww{H460F#zTZE$0X!vuv2%BsM)%w6UDuW%Z!W=@69Q}WM4NAK z!qO+%N>yUAsB7dUcgbu0LZV;FnV@p;|g5=X> zUy#DaJrByZ_n;HTII1`@0TRbPoffMHTkvKvBU)(8it#(kcQZeq`0HKUV%rO0PH%r9 z6SDp>q)_&S%=4->20Jn-__-J<{pX-Eml-c&)PMnTX*w5)$#sn7QGTJ^miVlgAw!Ao zz#V<`W@3NftZ74}2}UYmsqW{;hi8xZ_Cc z|9eV4Le&=0GV+L8xw}n#VXVkh?)_FyYqqFti!)>Rll{Zsx&>DK$(gG2&qV>q&|q@l z(oh)GL@BOGhh8?WQh|pz5__`nzzv!eu5@bO=#@`Ij)&b!(jo*~H2Ep@?A!mqZvUIq z;(&=n@()Tdr-9l5f(8tWC_X^Z9TNTrP>hK|0s>j>^ubV>KvcJ)1oQ*RYSBfl0>T*> z$B6nsH!(i6j|}e0|DYsY>@X=nQ^g_Vdmzk0u?P_X^qRf|g9B=>%3u-S|9P(t@Yp+d z@(P*}L4!c`|5?4JM(p=Je`2z5akz0vF2^E=kp7>z0RKNx0RaD7F2MhW3IOrHqXOtN zE?R2}yP777f|&t0N6V>l-ta^G5#1n0r_?BdNSmMuzz~ExrwS55V?c40CqW9g9NMs< z(U|w_PDMNh3qzwJ7CbqL?;Mfl>{xoZUncWOroyM>5fFz-F7=n*h+DwNMZWj;FQ;k$ zLdju#iqJV7ENoi=v!62!q)_G~(S?n>s&0}uN!?vd5t&T3!?kKE`0il9{jiM(44FMsNd?s5&en`^PK~9o$ z0;&xGfkuFVx#SF~4k3XfvY_G|d&HmTLNHaw=$no1a-CVLH$o+NhWuWb|LBhd@%adRNmw%fu5bczTLZE ze@f78YeZO^by*rgyHVCiIO{3M`CdlnAFxEWvb#{5x3(&T!T0fB?UN?j&qn_k6DMd1lU(xZ5Ym z>w@(o8;R*`Hh7WMiAJO|*sa2#sI6OlL6z#3mn{HR?(mGk<7mL01Ctdwk(w?6dz2;A zZOtMHU$pI}g58uZ1P;K`rcQ^vL!!p1pVMxsqx)q=wT1@gQ7j{7Pi)wy z(*eZ!V>#9~j-;LX&fJ3>HpSVNZ$pR=y|jp|>r3B4ob^Rk#z;f9cme3x!r^H)%#>sg~{7(eimrr4kia((bEk z0;h>Uw5(B?OqnJDCfI}vWz*pTL-z=>pXnRQGnr2@NyR+gK&ND|e?@g6UM3*!GW^kB1jwh6gZkJawLVZ0)T3amBm~gg9l#EBk8-9NpPNNL(sfbC*1DJ z0L3*(EnLig!ZY!gavBibLAP5)H@NQm3LWDVb4P#*a218KReTu>;85D z%WvMq6KkZTI;N*d+k9kjPJcZZ$&G*i#gHn9cCUHtpjtDE%JcW9K9jB`IN-w zO%p*C;NU0e=3i_}FRdj4k6|vkxuI|MYnhNu;XULCpb0cq(vW;#Ji$A+)Hdf^I~PhM zZQGK&YJAQH@*&@ggKbEy$zy>fFis{5w3zs*XJ*`@O$Q;eC}eF?0ZF*%lPZTNtJuFJ3X4 z>lsSD{O_pGV<2vM9l}reTYdM+)-YTaz%S$e{XU#@?H%>63=f@~ z)66#^k6N_V>~kTXC=SA5>f${6%RVIv8L@XdrN&8Dh)j1o*D(=0Vc(Ic*?(I;7m6*i zS!%ktwKyggSQ`|Db}23rv;W#1sQF!r9pnMZ5i3=Qo#NaEs!wl2bNkAWJd-0xQ-)ol?A6h~HZ_zVr)}M#`FwGl;^I z(=P6|;dzr^mULXVe^h3_KI-Hi0=Tgijm9AqWkokOG7fKF{q-pVuG-qSLW@{ms6J(K zHErBJH>`#2A0>=YK~dct4(Pa!Ox3R+jdmy_^%Gc72$uq|W&`0Aa;KDrrgw z!6-_6vIEoFOfnCmazdv!NmiqJA&jM2+X$WGDxw`aA6#$f;UFl!83+ z#ZQg`ngiRds!WfrBL1Isk5`9PDHDxN_7N~iiUvUyaQqa=wa&WXsPd0(#bWG3d2;&{>B31L6GLDNv;i?K`DLH=9diT~GNhYL-Zv zHbULJZX$ZrqmLX*G>pi7-)q{E4N!tFDy)wZ_|@l@MzR^MN>%>AmZh0h<(zRUU}C}_ zWU!V4w`(pp`_uR7f#wk8ahKV5{QAl8L}l97*;hc2U{`Hs7df{u70@XW^X$$>a@|lr z2B{PIJ1XDn9Q=*+#ox;)!x?f^#~vBG7Y`a)XPO*e@NS>QncC^RkdfegPIy0Clg_vX z`~J7OQGq!4%8T9|=BlJE7_Ooz0lp^^gH7anMV_lIr*iMzu@G_|%Tup{VG?x5>;+*e zY+}{#%S>m;6Gjlm(Eu4}ohcn5HJhpNXK`UylCSDWHaa}C7gG~Lm$FMFCf480+nQM; zD!8!`a?=e+@0=ZIv-To8BG{yZGDX3H19gNbl~V@nXtv$RPO@1mhB^2kU-LSU&Tn~> zVVrnJJhWZ{tsB@8{R}omaSa8T)FIHKpIzC6M|aGUQA>F4TL2I?nVK|@*hyf2Iwd*k zeyeU)dagPD84eRap69*eJtwn}0VD1U^ZVgHb%m#mg28$)baGxDh)PXm#XwtJt_|L_T>2BEgpgR1Ao0WU^aDyN?dF_CqPMu z>j(WmBVyhqQ82(%ID`q@7EDNME%k+3n9_$iGR_wS<)8;?*!Md&g`EiKJYRHAWEQkp ze>$}cn$F1;zcorsT}Dw#oJ%pK#cl+v#ZN9x$pJxTV?<#ffC={S|VVHxBTvH^9O`@R`3L@)$`0Uoh-Q=r~h+W6a_32*mgGu>g3iv z?EJbKNl$aGJ1JMFl>rJIviO3kyJlN1m+!t5mMS&FrY7vJ<+L@ z`o_PB3a`Y2qmXT1mia=5X_G=FVkOWVu(ussL)fO)v{;^MXx_2m9VsbVcqJp|It2TM8^{S?10E9uP)CZ*RzyCFmu>W~V0h`lA9 zC3GKXjU<>`F|&R#gh@PJCjqTEhpY)khXqb>$R8>m({;sy%#44PINL>tFih}Q%u8ni z|Etz*K2BCg3NP+n{}|gJNX8uP0(VW^(iL76z!9voa;!@E59uOt*#6fuA?z0oQ*RXS_p1+DucusNV1>%j4F)f)0Uv9XLF#R(Z+}m~qb}&7Tf6~h ztx0gkI=&0zeMoLS1-c-9Z1y)PC^JE-F90o4=-K-Bjda+SQ@s~W8g7Wywzu7d!v(Yu zHu9d6eB@YpavU!D=5yVy+I~ajdaDJn()bBRKH^)w=72{MxzQu9Y*V?Zy1Ua7@1Cv< z@M;b~D{*{g+28-2G`5$p@(W*4W2VS@@62Pjct=wf$%w{6NEu3U8dRJ{f1-|UNfE#u zl5@5LYCoW^8O=#-=14#6ET3?b?-a4-`x#gJk_e&+~FuZ7D7s)aREw(iC zMGF^48yY1D1~2DADrsO$8gIAM6bw+^HR17fn-RGy&Xe-?AYtpTPriZFI?>mFd-EUL zoTU)kBo;_!!Waa?Hz+@AD*G=pw0FgsiD>91%(Ae|lXGq#l|7{iI<=t>4yX2m1{Ag^ zE(FCC?^8WL-Sk;RJ@vAAX2x4#Y^6?6hFtCV8f4gHILRJ$*l-5ld$d~>KYmW3~ zg}I1XKHY=KbN1>gBxstBYtT4Phz}84_m_v{@GJ12e_@JeX`tGHI5t0^o0C|af)F@N zC|NF%PDyJb7dnxb&8zUVo52RGFx;2>*uh>|>&BXT-ec0AIN~2kGNO1yJoZQgfA^hM zPqnR3AFnNoTj*!kc(CD%9X}P&-$%oe$$bJ|vL}*!v?>{!P&Ncmd6(ZwfNi%)!?RO^<@bI0Q9&t_(T?NK!!dL|C29 zbjeUpgqf&QntGC0w|GBx;qQx4R0r<0J7mG9@+vyz^z5YK#*VwiKd)J_yy740(Y(Hah9RrDULXT85f?j?Sx zdsvAYTVr;kqM{2Z3NCLMl@X(#J6u#9j3CYpO})Qc3mzV7ml<0RuxiAOr=stH9VatNiHU4JfuTYg;f(qQUS@63|=dz0fNKA z-;kM(3Z!9^COr0ZycG-zizh#x5#24M!nBUC8&~$M+;ne3;af8tF>`siupO6uLlY+v z|FVMYTWN1AVBf%aMtpVwyjD)1sJ^AHCRCtfV7jwHzP(?ysVG$B@>g~FUCH=9K>lSu zX%^r7G1CxD4g>*0sF%d#w{x@>9JL-p6>54q6nZ+1c*%Ayp>Po;XmGM$MMT7^Jqk82 z`I78L6Qufqly%g(o*MMpz0Cy~c7=xlW$d`+a8lp(rzC`RjLMt=Qu8eXpX@W_=Xgdb za<6Lmisa<)FC&~IJp3{Q)7q5J729XS)dS&{x*b}ZC=PWa z5slsip>*2<^VV3%@(z;w$td+-k&Z0&7pgXe89+#JO#uhbJ z6=y=sg;EJOw|updx!MaIsMu_w?5}Ryxb8;tY?XTeWTfET0~nJK2}0A<=FM)TyenO+ za+4xa0lH~9_$$H#6mPt>^e?c1D&!LtOJ;m$+D)J7%4DCo0MV5lVO8wDRCG6Ty-}_N zJa}vJNQ0uqWh}ufmRXxagK0k))hS>2Ak)?pD$y~%eF_|VF6WPP_(tWlrP5AUwP$7E zUf39={!DkYK~oXUsBX_th>e0_mR3GD#gGsFOu!NnLMuR4{$06BJAil?NHNO*6UtRT)bzy6{XKayMuC}(u=|T~HWv}b!qIhUXVQ`k zp$OtVZ?g$)#>(64lKzV>Qjwvnv0HDsV%Fgh%=?66d!KOKf0LjaqZ5Jy9aJjdTnZRlIT?TF05lVra(5LTi_Eydz3p5PJciTd+;8?o*C~3BUa7@NJ0RUmaVY5E`*CcnnHj6*AzOHtma!ulkYJly*fLgH*Ky>Wxst?Tzcmz4-U-7e%F2dF;VQwvO%_fU;Q1A$7 z@ZM2Aa9?E#=Hp_iWK;8f?ynKhnC_a^hag7$)MLw)j7ZYjHOLz*p_t+FsmoqoQIfh? z{)fzgmGK6HH3(*aHpG1%9#4;jWdB3@-;+10z=d(^da}S1OfV}#LK=eJZJQn6Z#cV0 z8U3V?|1zU9v_TQS|2LeJ;eYk9g@oSee^P1^s31y#88IEONKe4;=fylQ#K5oW^l|7P zC9=;8P{aQjWY{o#Bw6!CBKrePJp^DsQk?omU~_<4HYA8|z_2ufkd{F0*)zB*5E>Yr zf{_Ml;gc{7fg(Z^e8xX9qxkPf%B=@1%mVPZ=?!w=Ke4$sRuZVJ!bQykiZ%^!Z2!az zuK?7Ne~6kWC}at+FBJF)ut3xOakLAdw)YLJ6ez~Kz=r_E7#Yx?z*r6s@IU^=!h1yk zjz+s>KD-C8K>8mNSPr1bG6VMkZa9x2PXNz$nhGNjC?+?;h5$tZW3Z2;@<0=mEnvrd zVW3C;bs+;48j<{8yYN_kbjm~mg9JvEp+Wk{I@b3?|0tFI zr5lwO7ywcLm?qxdp$PQ|JX_2th!03b2MkpT7)!hg6$#h^;x)1=&^BBSIS8orGeY{v z$O5l~{m8(>*N6LnDBZwe8vfa4R7HR62vptz&j$=Zpa$moFB^)(@Dw5~0}zCYFR1)q zsEi(HKc<_oFsDoxeN=ow$mn)_pj{KR87hjjlk)2Ow}byPC?m0oo3R{(N(9*B@UH4M z7slBT;#?u4A*CC3(R4~2Yw7bsM~6nY)upDVr>2KS$EUaLCbH4`U7mDXT8_F_)XT^? zA}Ik4DK)HpQTzz%EMi)&*n&S1gVYcU*K~alAz}PBBZLJ?h2>0zl|+RV1dm2WuJBs_ z$o$GIv~$ZUKL9t-(!dEA?*U9A=Mb3|#Tj>1C_OLDP%>~Y3URW0%Ia%yE6`)5%17$u zkdzFg8O_HjlesT89T5HgfHO?{dqRlKK#UId)^|2p*)}6>Op^P!*jf2mKJ2TR`>=T8 z4O)$YkDgTnz|TryNom0b(eU95q~(R{XCap_y*cnYk<<&C-EP~R4v2tqp1$nuKR#%` zo3KF_R|Hq5Z|(|o5h-|Bc{#1zt5FF2kMvboo^-rB&FO4yE4ge*R1DLRqzIY|F4>m;u`@YScvQU|NV4VyKu+iK9;UCFzbAKtx!KxOy zUk7RD-LH=mJY&P3cXLD(l%-lPHm8gz1%}8dSC(iBC73o$ZoHSf-KDCV zV4%I{DTSj{yVIy_y!VIw=cfr|q}T>}(-6k=;?0%jMTnzB?YjcNDuLA*WMB%~{-?Wb z28UNt#ACftcE5V#D%r5LQkSC&7`(0nXyrx3hy7~qeN^e$A8=^dX50sW3)VQVH$X<@p0+0M)`ZWFHmF^ z&CyP=*JkBEBp~Yu0I(2bzeqAL=T*9A`}~g9M5b;>6NfUeg2v9MzrKCkXKVYf@iw|SPKzv{IFWIhF#PV}fI~5@oWqCN&|;j-7KM6I)IYckQpwq#M6$GG95-{R+XK~u`M0~_c_Nrkh- zGv{2h0bmjlW0@X3T~9!;l$vp_H2Acdg(Y-1B}>~>k$Yr6fmN@E=jNkp?u0Ok86VzO zhtlntlM)>fV_u6*A$T>9CS(q1fZJWtWXgV}Zb5Tu0JNNNsH|opPc!IB+;(wd=sj%1 zBv@tjP48NaMsyt9<}?crH+Y5;p`diOjv0Lx^Gw9#g%s4ykWi><-aO8E+Gcvx5FdDk z;jSzVo6i!G8V&0xFXl<;*iQ!&D?dqv0IQ#dZjjO4R=dwwnE7Vu;t9ctq8OiZ5yB3p z9_|%~2Vfr*h>Q8!ALU(NVSH_Y0?-k%*l4$=NOpV*@t4WD_^NB#Iq`N?D#`h0J0hL} zJnofp19dy!8ymFa+b}`d`P;7exyBtaG~gYA=^{A@7PbFe$<^40p$ew>y|%RDl} zm{4q$eKl;oa>+bdtEFd`w$*gcBDXgcl2f5AFlyk=#lvv*y9K2Vh|!FuwIe0zS*Mp1 zg%hr2#G9pS8pU9KJocM$?$a17Ba76zc*xoM)6f@z~{yCMZc(%B>+71?}{oXZvC1ee6K`E^_N#beK z^G9ubXarc~NrXKVh!2DJWCjQw6iEWMGR(4k0*La<1!J5}H~YKiOjR_$mZVaD6an<^ z+Vc*($QTh#n7dG4pnq+ORj&>yu_zoL|N7+hdm2h85o;`~Y$sSZ6LFAuo;rGqJbLi$ zS5(~!r>Ik%7xv@0QN9`V3P1>%xrY&C&fCC?^K?+UIOs$r#WKm(qncA%in_}Jiwk{N z$se?xDKqa`KEciR7`~Y<8}@H-*C7DybZ|EUw5X}ep=b~gO5*cFJuGimSJBO%=oCKI zR1jTe0nPVQ;F%f>A7O73LUEq-&IrYe<2wT5TvRoF5a%c#X?SS8MM-7u9FYc~GRUJO*LHCL}L74SDBx$yR1wyYZzA3oM zH4hx*cGj7FucP@JfpL50I>VK7>``YOQr~B7wR_?-=pg(bp^6PN zrT)L7HJ#zc6ICbllxD`m-*uKr`NKkK|iXWe&DiJq^~70kgK$aF>h3*UL(nv$jTx zMW867z>SzNRfYd1o{M-zu_VzM?wrF`=(v?Xm3Tsaa7p~l}PS6RSza0G+nq~IYI0V!={|TQL?$#L1r4TVE1| zJHE`lr7Dl1xs@asAy&tHw5m+ZQJk=%V-Ex@U^uTNM*v6%7F!Da6kG0Dg1Y-vhi}p4 z4fW@HeZX?QJw@E(*Yws^&K!M0IylF?SXcelws@HUjWPJLJ49K_!Z76Y@v>Jw))T7C zyr%uGO_tHVX1y0-XUQi_jP>gnHN(}x59{5SsfOGbxD$_2jNxj99`txGDq)LD3AkK2 zKvbIg#E72~))zX8mg)~W%Pu0kSC!Y)8WO~`qSflo4!*v<&mL}=m^uRa8tTUfB7tz7 z@eM1piFZ=T-^lY1@!rn%Ruve!F~5El!-Uhx{lUM51p`i_1Fy3m&*k>hV$7QE0D}6p ziJ^NtWe|~D3O1S%CcIJjFzP0#$EciNzyv5^VQqQCpqYN*Rp|ho8p8USXS$K6eTI`X zU(`^%r(~tDQX$$d94fONkHQyFl*Q~JKWqvV zh}-ey_=z=MbAoZiXwmyz@~Z4E47lPyr|-32vxCg-HqMnTzi3^4%^_Ck->s??GTOeHa! zUPn;1ZU2mwBe)S!VUXySK%1G5Q!1iHPQ$zK2RmNw@UXzP?ejiW{%Dp6+s!1|CWwEb zJL2bQnDTjRsVbIz8`{?DftyJUN&Y(A@NVyENYoV%;VDzm-Ar*De;xJ z$nUF1Tl)_Fh)(9O4IQd-hv+r8`t!S~yY*j4QaElCn`Hb%!x^2KmF|BT&i&(=EGmOz zJj{kldk?s#G#QWg7u2FL&`W|t;T&;nXZ1~t`2kziJz(o>lLtk(SUCu6UP<8ps&3j; zp>p7!C?}aNLh<-AbLM|KLs-^KJus!X{K)wKD@9~vaCRv4)yk* zt^6S?YsAfH{8J1ipqnJS>a-YI>)@7&rXxgFc;WW56AvmLab=`e;|}UwSxbW&()Zhw z9pY--0E6UkH7WL(lJEUO?CGgT7^G%@YrU7JPWmn3wv{dpP znB#9+rJA0vua6eeU>sR_5-(?v^kY8{q6)b=(z>_?pFL&@cKc_w$fEP8>1Q^%{(yT1LVZ@KH_i`A{No%D}dSL^KvXzjZXAfCc# z;>6eQreA*ar~X-KELWOVe8>1agy)@T{Nh^wjr&elS(1VJF09 ze>L5~vW)0F`Zw^IGGXgpE`urKl87nN!sir^Zrfq>CQ66;1lpzTQo`ewqzq}#kp6Y+ zcxm)I*9PK`CQ-`TKE<4MQcFc&<}e7jKe89@C`876{A4bxmMIF)V2&kA^eIcBBIAR5 zat2xUftspUtsWkWYU!3lpJrrPA+_+aoQ&GOXg{<0`wv9Gn~_OkZ3dF-APwSNlouY^ zk;j$fHOk|T9fzy;K^*E@#0-8^QO`mi_gC1~la=uCx{BMUbL((TwxxiMH~rB~O&i2p z7M&%_cnqFAbOiB$+E$C@|B*Z=6o2jSxNA={NYn9e$>q?_K@sz$OrfGQ&yk zmSz?%d*PP7oKWYf?Q2m9Ni{9G_FIiNCUh*MA#qgAKs|GRr&T|S$-`^5SpE$_IgPnk zv+Y;^UgE>`(tbn7*baI}xJ&E~yVkh1U{k_rF0zDHG9@z=wZgt_QB~3m0xW>bb11Ej zyl{lGWNO1{3TtwWVWQaEbDLS%$KF%KPMfEro_EWvuEqZe%+S>im7&>;5cB{rj7MAs zNtJ;soBV}x<6|Ew$*oT1pVyB#eB%aNZ%8iJ#7pGl51zy=tn)<~8M8T1i$~Zx$gwdF zZQd{MzM)u=B((%gb}jKu%2zP4EhdYHFT#_2WgyFyi#)iwc|cdU2ZdzR7xGKIOKZF{ z_K*HFe?IOg2$WNPA$wXcXEFc$Bw^R{^F|#Qa;LU)b90xt5>u-3HyYD?mpDkQRpWT5 z2rsU2C;hlbbgIoEVUfO8pw*w?S6M~K8rAZmAC7Mre#=zuDgke-zK}sCmfKp%f@P)i z1;D(xdh%p&&uKVg#O&AaKu+wgN&mUCR)Y1H=+u*(#p@ZhbNZ%McCtExRI62Xu1~q8F=I@os4CQiSX^xz*Z9^mU_peb#5 z-X5DrNBS_;U=c6;*yKQ6SmaMu`N12p(Y4rGst*9vv3fN2`Y_CtV4bD-xjJ_!b8o>1 zpCTzQKE*ON7Etoi669Yj#19Rhh5Z8RAKpzV-t{VNeYymEa}Fr6Fi!MnM5A22g}zqr z0YO=_%EQ8cm*!5q$!F@ls4D3W{bMpTN|&RG$ir%L`*`XP9s5WuY0Fh<9`y;=XFjiX z3pC8d8XUYsWv6WISj}K&;opco`1TmN14>;MV4 zSeuBlN|yFidE<(Fy(%buiC>fEW*WW0d%5kyO+DaE04co$no1nho#t{xrT(Cz9pEay z^8LoiJ%viJPlLJ}fj9E4MBjToflcAhLnGCqdco{c6cMKh=~ti^$Cjzs8vD`jlSA1b zP9tpQD0I!Ys%9UqdJt#{QZKZE?66(O+SN$0l?>u243>QjJ#ldXUiX$!F|z_r)6C?* zTQ$5$=gxgqei}=$0*4OD{3_3Jdi0TPv=4ya86T^vdet}98b?2z@bK%3>=$8QQOb0m zavP_GnQEmBkr)FPo8B9Y4s)~Umo*aj8ry)lQ*N7cEntRMnz2sjO(Xbe7!8J9i_Jse z3lBw7vMZbXaKCL01}a_3Q+u67O>O^jGdPyQgiTP}r!WZAz2>0J9?bBb_pjQ5IaHIs z`i|<^9rQ;fg5&Gz65?C?SG!HwYwE7Iv~%`j+d@KYCJxOu1<59wQ&Rf%r%O?(sM1Bu zH4XjK3=ItISXq(NGKk|Q9#0%g1WKzZ5{@qi%3Dkp+tCgq!;fok$Tihbha`t#;s@tu zP=oeVm5dxac_IWZ-SWIqQ;6h!XA+HGVE_N@w2kDl7?I%fY&I5{GCB!kE2Y>gubE?Tp}UxNpg zk_bKdZ%`#D=&=7tcN-%B5cS8#(jF{oaMKYPlxDDl3rASef2635CUr>o;8`slK%|0G zjJe>c|6LYaAtdlv8>dMA%OJSW2nW{Qt-XyF2YW3)LWFSQR?3VtRlZyh2A? z02imiaWue1&2c!$byccBegT`&sA3O;#}$BrmI!I9iVg{MHTB}SgKL@Lv9-Zw_&pe7 z|7ug-H$XTDBP*aGOm;-f@Q^VESfE3whbtwaA(K=&gN6{hVhmtGf^l`9kW3++IRf;- zotds7K{V1OXka1XDdvIyDnZ-qAwqa&2Wb$}!5$i?Q9HpNQk*e2z+$5Zgt#sLYE$H3 zAsl?UI4}g@>D1stbR}PIk$!<)CCR{DfL)ydafiScjMNbZ!X4<0iu(o9ttKV}++)Ci z0*PAn!ouZ(%@W$-AWXOLmhekpd1pWo92?lflOnbhxHp}9*jRA!)B*G`+B?y9aCkW^9!?Q#W&8^z3w*C8_;4%!)u!0gAXEKYs}Y<4 zh}SzzEDo?$vn?!G7d++L8H9lrTN)M&M@t!fgag~3%A%ixhw`BwM3DW@>qie<2=U^V zKmb0tb{rm{2_E6(M`$l_Ej=4FWV=ilfL8^Nz=j?X7u>-67f#Ns@&%lKe&Kuk-;UofNGn-8ZK(w=0 zI*r_0slH+I>n9w zPcbG09ZV|Q=pTR-4Q8O<5CUI~qzlNbNQ|%{Eb3bOI3!^Iek_=7|0ug9KStymr8uHu z(fwbFcjNqTIF(bNWl-p#O;gsJ0d&Bx&>&Le$A8qvqBQ(U%73Yk`IfwHXibMn;J%Yo z6dCY?q_>YJxf*?6DqpT2{CAJn*vnRZ=hi$QK-$~K@4Yb<*3_HHj5WVJ#b-&}01KJA zHhKI!3C$RfIG^W#)e_t6cG8h`icqYfU(ap`c&ix;Wk=LO9R|xCE8Hy|TT3JLej{|6f3>x99tYsx zVW|+hz{Ma0#0&5ZLez!ATLQIWlZopJ>@6}Ot_qa5(3GYx%%_p zCrDNVixNBls&(|=;11%&5p%&_CuZPLz(uhVxIyqUNJl8C?5>+{EY8u6GaUt7^ z#UY9zc(^qtD3Dz^c?8qoUuU&e36B3tDN&{14J1X61iIrt6HlQPh9nDVDd0fv-DiDd zLa@&cDtK@@QawEyWTZc_QRl(lIsD_mGx69!f_$?sC%{dCr|LNkumv|LAwYtp7^%8I zZni)-juP0Dd^11+JiH`sWC2L0>zG&nYE#%0AOzscUE1JR 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

knp;vs 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 z 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 z

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 Date: Sat, 10 Oct 2015 13:54:16 +0200 Subject: [PATCH 22/77] Dummy edit to trigger CI. --- Readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Readme.md b/Readme.md index ed1911a78..eb16dc0f4 100644 --- a/Readme.md +++ b/Readme.md @@ -126,4 +126,3 @@ Our license is based on the modified, __3-clause BSD__-License. An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp. For the legal details, see the `LICENSE` file. - From 62ec784cef7cedd3ec66d1e3d42d52a3c1f82f0a Mon Sep 17 00:00:00 2001 From: Sebastien Bonopera Date: Mon, 12 Oct 2015 20:08:25 +0200 Subject: [PATCH 23/77] Fixed issue in PlyParser (uint16 values misparsed) --- code/PlyParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index db4c2b5d4..8d6ce0698 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -857,7 +857,7 @@ bool PLY::PropertyInstance::ParseValueBinary( case EDT_UShort: { - int16_t i = *((uint16_t*)pCur); + uint16_t i = *((uint16_t*)pCur); // Swap endianess if (p_bBE)ByteSwap::Swap(&i); From 2750f8da2499f16ebe152056c6df479591b19684 Mon Sep 17 00:00:00 2001 From: Francesco Guastella Date: Thu, 15 Oct 2015 15:46:35 +0200 Subject: [PATCH 24/77] Added support for reflection maps for OBJ files --- code/ObjFileData.h | 8 ++++++ code/ObjFileImporter.cpp | 16 +++++++++++ code/ObjFileMtlImporter.cpp | 57 +++++++++++++++++++++++++++++++++---- code/ObjFileMtlImporter.h | 3 +- 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/code/ObjFileData.h b/code/ObjFileData.h index 2d5100ba8..9aa44576b 100644 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -156,6 +156,7 @@ struct Material aiString textureEmissive; aiString textureBump; aiString textureNormal; + aiString textureReflection[6]; aiString textureSpecularity; aiString textureOpacity; aiString textureDisp; @@ -167,6 +168,13 @@ struct Material TextureEmissiveType, TextureBumpType, TextureNormalType, + TextureReflectionSphereType, + TextureReflectionCubeTopType, + TextureReflectionCubeBottomType, + TextureReflectionCubeFrontType, + TextureReflectionCubeBackType, + TextureReflectionCubeLeftType, + TextureReflectionCubeRightType, TextureSpecularityType, TextureOpacityType, TextureDispType, diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 7bf6154df..ebf75b3c4 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -636,6 +636,22 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc } } + if( 0 != pCurrentMaterial->textureReflection[0].length ) + { + ObjFile::Material::TextureType type = 0 != pCurrentMaterial->textureReflection[1].length ? + ObjFile::Material::TextureReflectionCubeTopType : + ObjFile::Material::TextureReflectionSphereType; + + unsigned count = type == ObjFile::Material::TextureReflectionSphereType ? 1 : 6; + for( unsigned i = 0; i < count; i++ ) + mat->AddProperty(&pCurrentMaterial->textureReflection[i], AI_MATKEY_TEXTURE_REFLECTION(i)); + + if(pCurrentMaterial->clamp[type]) + //TODO addTextureMappingModeProperty should accept an index to handle clamp option for each + //texture of a cubemap + addTextureMappingModeProperty(mat, aiTextureType_REFLECTION); + } + if ( 0 != pCurrentMaterial->textureDisp.length ) { mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) ); diff --git a/code/ObjFileMtlImporter.cpp b/code/ObjFileMtlImporter.cpp index c993cd203..5b5160a44 100644 --- a/code/ObjFileMtlImporter.cpp +++ b/code/ObjFileMtlImporter.cpp @@ -64,6 +64,7 @@ static const std::string BumpTexture1 = "map_bump"; static const std::string BumpTexture2 = "map_Bump"; static const std::string BumpTexture3 = "bump"; static const std::string NormalTexture = "map_Kn"; +static const std::string ReflectionTexture = "refl"; static const std::string DisplacementTexture = "disp"; static const std::string SpecularityTexture = "map_ns"; @@ -200,6 +201,7 @@ void ObjFileMtlImporter::load() case 'm': // Texture case 'b': // quick'n'dirty - for 'bump' sections + case 'r': // quick'n'dirty - for 'refl' sections { getTexture(); m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); @@ -332,6 +334,9 @@ void ObjFileMtlImporter::getTexture() { // Normal map out = & m_pModel->m_pCurrentMaterial->textureNormal; clampIndex = ObjFile::Material::TextureNormalType; + } else if(!ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), ReflectionTexture.size() ) ) { + // Reflection texture(s) + //Do nothing here } else if (!ASSIMP_strincmp( pPtr, DisplacementTexture.c_str(), DisplacementTexture.size() ) ) { // Displacement texture out = &m_pModel->m_pCurrentMaterial->textureDisp; @@ -346,7 +351,7 @@ void ObjFileMtlImporter::getTexture() { } bool clamp = false; - getTextureOption(clamp); + getTextureOption(clamp, clampIndex, out); m_pModel->m_pCurrentMaterial->clamp[clampIndex] = clamp; std::string texture; @@ -369,7 +374,7 @@ void ObjFileMtlImporter::getTexture() { * Because aiMaterial supports clamp option, so we also want to return it * ///////////////////////////////////////////////////////////////////////////// */ -void ObjFileMtlImporter::getTextureOption(bool &clamp) +void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString *&out) { m_DataIt = getNextToken(m_DataIt, m_DataItEnd); @@ -392,13 +397,55 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp) skipToken = 2; } - else if ( !ASSIMP_strincmp(pPtr, BlendUOption.c_str(), BlendUOption.size()) + else if( !ASSIMP_strincmp( pPtr, TypeOption.c_str(), TypeOption.size() ) ) + { + DataArrayIt it = getNextToken( m_DataIt, m_DataItEnd ); + char value[ 12 ]; + CopyNextWord( it, m_DataItEnd, value, sizeof( value ) / sizeof( *value ) ); + if( !ASSIMP_strincmp( value, "cube_top", 8 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeTopType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[0]; + } + else if( !ASSIMP_strincmp( value, "cube_bottom", 11 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeBottomType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[1]; + } + else if( !ASSIMP_strincmp( value, "cube_front", 10 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeFrontType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[2]; + } + else if( !ASSIMP_strincmp( value, "cube_back", 9 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeBackType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[3]; + } + else if( !ASSIMP_strincmp( value, "cube_left", 9 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeLeftType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[4]; + } + else if( !ASSIMP_strincmp( value, "cube_right", 10 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeRightType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[5]; + } + else if( !ASSIMP_strincmp( value, "sphere", 6 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionSphereType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[0]; + } + + skipToken = 2; + } + else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), BlendUOption.size()) || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), BlendVOption.size()) || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), BoostOption.size()) || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), ResolutionOption.size()) || !ASSIMP_strincmp(pPtr, BumpOption.c_str(), BumpOption.size()) - || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), ChannelOption.size()) - || !ASSIMP_strincmp(pPtr, TypeOption.c_str(), TypeOption.size()) ) + || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), ChannelOption.size())) { skipToken = 2; } diff --git a/code/ObjFileMtlImporter.h b/code/ObjFileMtlImporter.h index 3278e380b..8bcfc51e1 100644 --- a/code/ObjFileMtlImporter.h +++ b/code/ObjFileMtlImporter.h @@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include struct aiColor3D; +struct aiString; namespace Assimp { @@ -89,7 +90,7 @@ private: void createMaterial(); /// Get texture name from loaded data. void getTexture(); - void getTextureOption(bool &clamp); + void getTextureOption(bool &clamp, int &clampIndex, aiString *&out); private: //! Absolute pathname From adb88aecde2ecde6d73013d6926e22c99c34fad2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Oct 2015 13:57:29 +0200 Subject: [PATCH 25/77] Update Readme.md Add link to webirc-client to join assetimporterlib channel on freenode. --- Readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index eb16dc0f4..1a99bf873 100644 --- a/Readme.md +++ b/Readme.md @@ -113,7 +113,9 @@ If the docs don't solve your problem, ask on [StackOverflow](http://stackoverflo For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_ [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) -And we also have an IRC-channel at freenode: #assetimporterlib . +And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type +> /join #assetimporterlib + ### Contributing ### Contributions to assimp are highly appreciated. The easiest way to get involved is to submit From 3274bcf8d689b898744603c67ec16a8e27105910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Twardu=C5=9B?= Date: Mon, 19 Oct 2015 22:07:32 +0200 Subject: [PATCH 26/77] Properly build path to the mtl file when loading loading obj --- code/ObjFileImporter.cpp | 2 +- code/ObjFileParser.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index ebf75b3c4..622584138 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -138,7 +138,7 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if ( pos != std::string::npos ) { modelName = pFile.substr(pos+1, pFile.size() - pos - 1); folderName = pFile.substr( 0, pos ); - if ( folderName.empty() ) { + if ( !folderName.empty() ) { pIOHandler->PushDirectory( folderName ); } } else { diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index 027d99543..83262b5d4 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -414,7 +414,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) if ( pIndices->empty() ) { DefaultLogger::get()->error("Obj: Ignoring empty face"); - // skip line and clean up + // skip line and clean up m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); delete pNormalID; delete pTexID; @@ -539,7 +539,10 @@ void ObjFileParser::getMaterialLib() const std::string strMatName(pStart, &(*m_DataIt)); std::string absName; if ( m_pIO->StackSize() > 0 ) { - const std::string &path = m_pIO->CurrentDirectory(); + std::string path = m_pIO->CurrentDirectory(); + if ( '/' != *path.rbegin() ) { + path += '/'; + } absName = path + strMatName; } else { absName = strMatName; From 12ed07a9399bbddd11bc101cacd7abbfb8bdb26b Mon Sep 17 00:00:00 2001 From: Olli Kallioinen Date: Tue, 27 Oct 2015 21:03:24 +0200 Subject: [PATCH 27/77] FBX import: If animation is not defining keys for all vector components (x, y and z), use the node transform as the default value. --- code/FBXConverter.cpp | 49 ++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index e0c6b9ca2..3d1e5caa6 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -2496,8 +2496,9 @@ private: // need to convert from TRS order to SRT? if(reverse_order) { - aiVector3D def_scale, def_translate; - aiQuaternion def_rot; + aiVector3D def_scale = PropertyGet(props,"Lcl Scaling",aiVector3D(1.f,1.f,1.f)); + aiVector3D def_translate = PropertyGet(props,"Lcl Translation",aiVector3D(0.f,0.f,0.f)); + aiVector3D def_rot = PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)); KeyFrameListList scaling; KeyFrameListList translation; @@ -2506,24 +2507,14 @@ private: if(chain[TransformationComp_Scaling] != iter_end) { scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop); } - else { - def_scale = PropertyGet(props,"Lcl Scaling",aiVector3D(1.f,1.f,1.f)); - } if(chain[TransformationComp_Translation] != iter_end) { translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop); } - else { - def_translate = PropertyGet(props,"Lcl Translation",aiVector3D(0.f,0.f,0.f)); - } if(chain[TransformationComp_Rotation] != iter_end) { rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop); } - else { - def_rot = EulerToQuaternion(PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)), - target.RotationOrder()); - } KeyFrameListList joined; joined.insert(joined.end(), scaling.begin(), scaling.end()); @@ -2740,7 +2731,7 @@ private: // ------------------------------------------------------------------------------------------------ void InterpolateKeys(aiVectorKey* valOut,const KeyTimeList& keys, const KeyFrameListList& inputs, - const bool geom, + const aiVector3D& def_value, double& max_time, double& min_time) @@ -2754,10 +2745,7 @@ private: next_pos.resize(inputs.size(),0); BOOST_FOREACH(KeyTimeList::value_type time, keys) { - float result[3] = {0.0f, 0.0f, 0.0f}; - if(geom) { - result[0] = result[1] = result[2] = 1.0f; - } + float result[3] = {def_value.x, def_value.y, def_value.z}; for (size_t i = 0; i < count; ++i) { const KeyFrameList& kfl = inputs[i]; @@ -2782,12 +2770,7 @@ private: const double factor = timeB == timeA ? 0. : static_cast((time - timeA) / (timeB - timeA)); const float interpValue = static_cast(valueA + (valueB - valueA) * factor); - if(geom) { - result[kfl.get<2>()] *= interpValue; - } - else { - result[kfl.get<2>()] += interpValue; - } + result[kfl.get<2>()] = interpValue; } // magic value to convert fbx times to seconds @@ -2807,7 +2790,7 @@ private: // ------------------------------------------------------------------------------------------------ void InterpolateKeys(aiQuatKey* valOut,const KeyTimeList& keys, const KeyFrameListList& inputs, - const bool geom, + const aiVector3D& def_value, double& maxTime, double& minTime, Model::RotOrder order) @@ -2816,7 +2799,7 @@ private: ai_assert(valOut); boost::scoped_array temp(new aiVectorKey[keys.size()]); - InterpolateKeys(temp.get(),keys,inputs,geom,maxTime, minTime); + InterpolateKeys(temp.get(), keys, inputs, def_value, maxTime, minTime); aiMatrix4x4 m; @@ -2858,20 +2841,20 @@ private: Model::RotOrder order, const aiVector3D& def_scale, const aiVector3D& def_translate, - const aiQuaternion& def_rotation) + const aiVector3D& def_rotation) { if (rotation.size()) { - InterpolateKeys(out_quat, times, rotation, false, maxTime, minTime, order); + InterpolateKeys(out_quat, times, rotation, def_rotation, maxTime, minTime, order); } else { for (size_t i = 0; i < times.size(); ++i) { out_quat[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; - out_quat[i].mValue = def_rotation; + out_quat[i].mValue = EulerToQuaternion(def_rotation, order); } } if (scaling.size()) { - InterpolateKeys(out_scale, times, scaling, true, maxTime, minTime); + InterpolateKeys(out_scale, times, scaling, def_scale, maxTime, minTime); } else { for (size_t i = 0; i < times.size(); ++i) { @@ -2881,7 +2864,7 @@ private: } if (translation.size()) { - InterpolateKeys(out_translation, times, translation, false, maxTime, minTime); + InterpolateKeys(out_translation, times, translation, def_translate, maxTime, minTime); } else { for (size_t i = 0; i < times.size(); ++i) { @@ -2935,7 +2918,7 @@ private: na->mNumScalingKeys = static_cast(keys.size()); na->mScalingKeys = new aiVectorKey[keys.size()]; if (keys.size() > 0) - InterpolateKeys(na->mScalingKeys, keys, inputs, true, maxTime, minTime); + InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime); } @@ -2955,7 +2938,7 @@ private: na->mNumPositionKeys = static_cast(keys.size()); na->mPositionKeys = new aiVectorKey[keys.size()]; if (keys.size() > 0) - InterpolateKeys(na->mPositionKeys, keys, inputs, false, maxTime, minTime); + InterpolateKeys(na->mPositionKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime); } @@ -2976,7 +2959,7 @@ private: na->mNumRotationKeys = static_cast(keys.size()); na->mRotationKeys = new aiQuatKey[keys.size()]; if (keys.size() > 0) - InterpolateKeys(na->mRotationKeys, keys, inputs, false, maxTime, minTime, order); + InterpolateKeys(na->mRotationKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime, order); } From fba7ede639e746e282448cf238cd7d59790dec61 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 28 Oct 2015 13:30:56 +0200 Subject: [PATCH 28/77] OFFLoader: Don't use assignments as expressions --- code/OFFLoader.cpp | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index d5c23dcfa..d801a2eb0 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -138,9 +138,15 @@ void OFFImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError("OFF: There are no valid faces"); } - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = 1 ]; - aiMesh* mesh = pScene->mMeshes[0] = new aiMesh(); - aiFace* faces = mesh->mFaces = new aiFace [mesh->mNumFaces = numFaces]; + pScene->mNumMeshes = 1; + pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; + + aiMesh* mesh = new aiMesh(); + pScene->mMeshes[0] = mesh; + + mesh->mNumFaces = numFaces; + aiFace* faces = new aiFace [mesh->mNumFaces]; + mesh->mFaces = faces; std::vector tempPositions(numVertices); @@ -171,7 +177,8 @@ void OFFImporter::InternReadFile( const std::string& pFile, break; } sz = line;SkipSpaces(&sz); - if(!(faces->mNumIndices = strtoul10(sz,&sz)) || faces->mNumIndices > 9) + faces->mNumIndices = strtoul10(sz,&sz); + if(!(faces->mNumIndices) || faces->mNumIndices > 9) { DefaultLogger::get()->error("OFF: Faces with zero indices aren't allowed"); --mesh->mNumFaces; @@ -185,24 +192,28 @@ void OFFImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError("OFF: There are no valid faces"); // allocate storage for the output vertices - aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + aiVector3D* verts = new aiVector3D[mesh->mNumVertices]; + mesh->mVertices = verts; // second: now parse all face indices - buffer = old;faces = mesh->mFaces; + buffer = old; + faces = mesh->mFaces; for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;) { if(!GetNextLine(buffer,line))break; unsigned int idx; sz = line;SkipSpaces(&sz); - if(!(idx = strtoul10(sz,&sz)) || idx > 9) + idx = strtoul10(sz,&sz); + if(!(idx) || idx > 9) continue; faces->mIndices = new unsigned int [faces->mNumIndices]; for (unsigned int m = 0; m < faces->mNumIndices;++m) { SkipSpaces(&sz); - if ((idx = strtoul10(sz,&sz)) >= numVertices) + idx = strtoul10(sz,&sz); + if ((idx) >= numVertices) { DefaultLogger::get()->error("OFF: Vertex index is out of range"); idx = numVertices-1; @@ -217,11 +228,13 @@ void OFFImporter::InternReadFile( const std::string& pFile, // generate the output node graph pScene->mRootNode = new aiNode(); pScene->mRootNode->mName.Set(""); - pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes = 1]; + pScene->mRootNode->mNumMeshes = 1; + pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes]; pScene->mRootNode->mMeshes[0] = 0; // generate a default material - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = 1]; + pScene->mNumMaterials = 1; + pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; aiMaterial* pcMat = new aiMaterial(); aiColor4D clr(0.6f,0.6f,0.6f,1.0f); From 7a5bc6eca34dd6a58f230acdada74248cfc95e5a Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 28 Oct 2015 14:10:18 +0200 Subject: [PATCH 29/77] OFFLoader: Use a temporary vector to store vertices instead of a raw array Prevents crash on certain malformed inputs but they still cause a validation failure. --- code/OFFLoader.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index d801a2eb0..ea563ca9e 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -192,8 +192,8 @@ void OFFImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError("OFF: There are no valid faces"); // allocate storage for the output vertices - aiVector3D* verts = new aiVector3D[mesh->mNumVertices]; - mesh->mVertices = verts; + std::vector verts; + verts.reserve(mesh->mNumVertices); // second: now parse all face indices buffer = old; @@ -219,12 +219,14 @@ void OFFImporter::InternReadFile( const std::string& pFile, idx = numVertices-1; } faces->mIndices[m] = p++; - *verts++ = tempPositions[idx]; + verts.push_back(tempPositions[idx]); } ++i; ++faces; } + mesh->mVertices = new aiVector3D[verts.size()]; + memcpy(mesh->mVertices, &verts[0], verts.size() * sizeof(aiVector3D)); // generate the output node graph pScene->mRootNode = new aiNode(); pScene->mRootNode->mName.Set(""); From 9825d07764b9934ab2a88fa05f9f5edba4beb8e2 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 28 Oct 2015 14:20:13 +0200 Subject: [PATCH 30/77] OFFLoader: Throw error on certain invalid files instead of failing validation later --- code/OFFLoader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index ea563ca9e..7e4429c88 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -225,6 +225,9 @@ void OFFImporter::InternReadFile( const std::string& pFile, ++faces; } + if (mesh->mNumVertices != verts.size()) { + throw DeadlyImportError("OFF: Vertex count mismatch"); + } mesh->mVertices = new aiVector3D[verts.size()]; memcpy(mesh->mVertices, &verts[0], verts.size() * sizeof(aiVector3D)); // generate the output node graph From 280641cee6f5c7e214e169f9addb75e93103ae65 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 28 Oct 2015 14:55:21 +0200 Subject: [PATCH 31/77] Add a testcase for invalid OFF file Testcase generated by AFL which used to crash the OFF loader --- test/models/OFF/invalid.off | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 test/models/OFF/invalid.off diff --git a/test/models/OFF/invalid.off b/test/models/OFF/invalid.off new file mode 100644 index 000000000..7ceb8bf85 --- /dev/null +++ b/test/models/OFF/invalid.off @@ -0,0 +1,8 @@ +OFF +3 4 +0.1 0.2 0.3 +0.2 0.3 0.4 +0.3 0.4 0.5 +0 +2 20 +4 From 46121a1559671cbeaa5bd089b4652b794b50d94e Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Thu, 29 Oct 2015 14:04:23 +0200 Subject: [PATCH 32/77] Mark single-parameter constructors explicit Suggested by cppcheck --- code/ASEParser.h | 4 ++-- code/Assimp.cpp | 2 +- code/BVHLoader.h | 2 +- code/BaseImporter.h | 2 +- code/BaseProcess.h | 4 ++-- code/CInterfaceIOWrapper.h | 4 ++-- code/ComputeUVMappingProcess.h | 2 +- code/FBXProperties.h | 2 +- code/IRRLoader.h | 4 ++-- code/Importer.h | 2 +- code/LWOFileData.h | 4 ++-- code/MD5Parser.h | 6 +++--- code/ObjFileData.h | 2 +- code/OgreStructs.h | 4 ++-- code/OgreXmlSerializer.h | 2 +- code/Q3BSPZipArchive.h | 2 +- code/Q3DLoader.h | 2 +- code/RawLoader.h | 4 ++-- code/SGSpatialSort.h | 2 +- code/SceneCombiner.h | 2 +- code/StdOStreamLogStream.h | 2 +- code/TinyFormatter.h | 2 +- code/UnrealLoader.h | 2 +- code/XFileHelper.h | 4 ++-- code/XFileParser.h | 2 +- code/irrXMLWrapper.h | 2 +- include/assimp/DefaultLogger.hpp | 2 +- include/assimp/Logger.hpp | 2 +- include/assimp/color4.h | 2 +- include/assimp/quaternion.h | 4 ++-- include/assimp/scene.h | 2 +- include/assimp/types.h | 2 +- 32 files changed, 43 insertions(+), 43 deletions(-) diff --git a/code/ASEParser.h b/code/ASEParser.h index e0a628606..da4f7bd48 100644 --- a/code/ASEParser.h +++ b/code/ASEParser.h @@ -138,7 +138,7 @@ struct Bone } //! Construction from an existing name - Bone( const std::string& name) + explicit Bone( const std::string& name) : mName (name) {} @@ -216,7 +216,7 @@ struct BaseNode enum Type {Light, Camera, Mesh, Dummy} mType; //! Constructor. Creates a default name for the node - BaseNode(Type _mType) + explicit BaseNode(Type _mType) : mType (_mType) , mProcessed (false) { diff --git a/code/Assimp.cpp b/code/Assimp.cpp index 03c39671b..497cb9b72 100644 --- a/code/Assimp.cpp +++ b/code/Assimp.cpp @@ -110,7 +110,7 @@ static boost::mutex gLogStreamMutex; class LogToCallbackRedirector : public LogStream { public: - LogToCallbackRedirector(const aiLogStream& s) + explicit LogToCallbackRedirector(const aiLogStream& s) : stream (s) { ai_assert(NULL != s.callback); } diff --git a/code/BVHLoader.h b/code/BVHLoader.h index 8c88484f6..5d950e3c7 100644 --- a/code/BVHLoader.h +++ b/code/BVHLoader.h @@ -83,7 +83,7 @@ class BVHLoader : public BaseImporter std::vector mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames Node() { } - Node( const aiNode* pNode) : mNode( pNode) { } + explicit Node( const aiNode* pNode) : mNode( pNode) { } }; public: diff --git a/code/BaseImporter.h b/code/BaseImporter.h index e8ed7460d..cb6394ebc 100644 --- a/code/BaseImporter.h +++ b/code/BaseImporter.h @@ -70,7 +70,7 @@ class IOStream; template struct ScopeGuard { - ScopeGuard(T* obj) : obj(obj), mdismiss() {} + explicit ScopeGuard(T* obj) : obj(obj), mdismiss() {} ~ScopeGuard () throw() { if (!mdismiss) { delete obj; diff --git a/code/BaseProcess.h b/code/BaseProcess.h index 0e7530f16..25a3f1e53 100644 --- a/code/BaseProcess.h +++ b/code/BaseProcess.h @@ -74,7 +74,7 @@ public: template struct THeapData : public Base { - THeapData(T* in) + explicit THeapData(T* in) : data (in) {} @@ -89,7 +89,7 @@ public: template struct TStaticData : public Base { - TStaticData(T in) + explicit TStaticData(T in) : data (in) {} diff --git a/code/CInterfaceIOWrapper.h b/code/CInterfaceIOWrapper.h index a9437b551..13e5c3de3 100644 --- a/code/CInterfaceIOWrapper.h +++ b/code/CInterfaceIOWrapper.h @@ -57,7 +57,7 @@ class CIOStreamWrapper : public IOStream friend class CIOSystemWrapper; public: - CIOStreamWrapper(aiFile* pFile) + explicit CIOStreamWrapper(aiFile* pFile) : mFile(pFile) {} @@ -110,7 +110,7 @@ private: class CIOSystemWrapper : public IOSystem { public: - CIOSystemWrapper(aiFileIO* pFile) + explicit CIOSystemWrapper(aiFileIO* pFile) : mFileSystem(pFile) {} diff --git a/code/ComputeUVMappingProcess.h b/code/ComputeUVMappingProcess.h index 4b829eda5..476af0451 100644 --- a/code/ComputeUVMappingProcess.h +++ b/code/ComputeUVMappingProcess.h @@ -125,7 +125,7 @@ private: // temporary structure to describe a mapping struct MappingInfo { - MappingInfo(aiTextureMapping _type) + explicit MappingInfo(aiTextureMapping _type) : type (_type) , axis (0.f,1.f,0.f) , uv (0u) diff --git a/code/FBXProperties.h b/code/FBXProperties.h index 455a2aedb..93b89c34c 100644 --- a/code/FBXProperties.h +++ b/code/FBXProperties.h @@ -87,7 +87,7 @@ class TypedProperty : public Property { public: - TypedProperty(const T& value) + explicit TypedProperty(const T& value) : value(value) { } diff --git a/code/IRRLoader.h b/code/IRRLoader.h index 04a65a24b..fa5c4e89b 100644 --- a/code/IRRLoader.h +++ b/code/IRRLoader.h @@ -113,7 +113,7 @@ private: } type; - Animator(AT t = UNKNOWN) + explicit Animator(AT t = UNKNOWN) : type (t) , speed (0.001f) , direction (0.f,1.f,0.f) @@ -163,7 +163,7 @@ private: ANIMMESH } type; - Node(ET t) + explicit Node(ET t) : type (t) , scaling (1.f,1.f,1.f) // assume uniform scaling by default , parent() diff --git a/code/Importer.h b/code/Importer.h index fbf9826ea..f0c32b42d 100644 --- a/code/Importer.h +++ b/code/Importer.h @@ -167,7 +167,7 @@ public: // ------------------------------------------------------------------- /** Construct a batch loader from a given IO system to be used * to acess external files */ - BatchLoader(IOSystem* pIO); + explicit BatchLoader(IOSystem* pIO); ~BatchLoader(); diff --git a/code/LWOFileData.h b/code/LWOFileData.h index 5838b5026..fee874c36 100644 --- a/code/LWOFileData.h +++ b/code/LWOFileData.h @@ -269,7 +269,7 @@ struct Face : public aiFace {} //! Construction from given type - Face(uint32_t _type) + explicit Face(uint32_t _type) : surfaceIndex (0) , smoothGroup (0) , type (_type) @@ -305,7 +305,7 @@ struct Face : public aiFace */ struct VMapEntry { - VMapEntry(unsigned int _dims) + explicit VMapEntry(unsigned int _dims) : dims(_dims) {} diff --git a/code/MD5Parser.h b/code/MD5Parser.h index e08d6d8b4..1938cca8b 100644 --- a/code/MD5Parser.h +++ b/code/MD5Parser.h @@ -280,7 +280,7 @@ public: * * @param mSections List of file sections (output of MD5Parser) */ - MD5MeshParser(SectionList& mSections); + explicit MD5MeshParser(SectionList& mSections); //! List of all meshes MeshList mMeshes; @@ -305,7 +305,7 @@ public: * * @param mSections List of file sections (output of MD5Parser) */ - MD5AnimParser(SectionList& mSections); + explicit MD5AnimParser(SectionList& mSections); //! Output frame rate @@ -337,7 +337,7 @@ public: * * @param mSections List of file sections (output of MD5Parser) */ - MD5CameraParser(SectionList& mSections); + explicit MD5CameraParser(SectionList& mSections); //! Output frame rate diff --git a/code/ObjFileData.h b/code/ObjFileData.h index 9aa44576b..8b5393b77 100644 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -242,7 +242,7 @@ struct Mesh { bool m_hasNormals; /// Constructor - Mesh( const std::string &name ) + explicit Mesh( const std::string &name ) : m_name( name ) , m_pMaterial(NULL) , m_uiNumIndices(0) diff --git a/code/OgreStructs.h b/code/OgreStructs.h index a18bac379..a184ed655 100644 --- a/code/OgreStructs.h +++ b/code/OgreStructs.h @@ -381,8 +381,8 @@ typedef std::vector VertexAnimationTrackList; class Animation { public: - Animation(Skeleton *parent); - Animation(Mesh *parent); + explicit Animation(Skeleton *parent); + explicit Animation(Mesh *parent); /// Returns the associated vertex data for a track in this animation. /** @note Only valid to call when parent Mesh is set. */ diff --git a/code/OgreXmlSerializer.h b/code/OgreXmlSerializer.h index feb288983..beddb8080 100644 --- a/code/OgreXmlSerializer.h +++ b/code/OgreXmlSerializer.h @@ -69,7 +69,7 @@ public: static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh); private: - OgreXmlSerializer(XmlReader *reader) : + explicit OgreXmlSerializer(XmlReader *reader) : m_reader(reader) { } diff --git a/code/Q3BSPZipArchive.h b/code/Q3BSPZipArchive.h index 333db5960..3b9bc2b3f 100644 --- a/code/Q3BSPZipArchive.h +++ b/code/Q3BSPZipArchive.h @@ -90,7 +90,7 @@ class ZipFile : public IOStream { public: - ZipFile(size_t size); + explicit ZipFile(size_t size); ~ZipFile(); diff --git a/code/Q3DLoader.h b/code/Q3DLoader.h index 02eb0a426..b957e91af 100644 --- a/code/Q3DLoader.h +++ b/code/Q3DLoader.h @@ -103,7 +103,7 @@ private: struct Face { - Face(unsigned int s) + explicit Face(unsigned int s) : indices (s) , uvindices (s) , mat (0) diff --git a/code/RawLoader.h b/code/RawLoader.h index 85d52c795..6dcc3c868 100644 --- a/code/RawLoader.h +++ b/code/RawLoader.h @@ -88,7 +88,7 @@ private: struct MeshInformation { - MeshInformation(const std::string& _name) + explicit MeshInformation(const std::string& _name) : name(_name) { vertices.reserve(100); @@ -103,7 +103,7 @@ private: struct GroupInformation { - GroupInformation(const std::string& _name) + explicit GroupInformation(const std::string& _name) : name(_name) { meshes.reserve(10); diff --git a/code/SGSpatialSort.h b/code/SGSpatialSort.h index e60ee59d2..d2277b583 100644 --- a/code/SGSpatialSort.h +++ b/code/SGSpatialSort.h @@ -66,7 +66,7 @@ public: /** Construction from a given face array, handling smoothing groups * properly */ - SGSpatialSort(const std::vector& vPositions); + explicit SGSpatialSort(const std::vector& vPositions); // ------------------------------------------------------------------- /** Add a vertex to the spatial sort diff --git a/code/SceneCombiner.h b/code/SceneCombiner.h index 3e6f0da41..cc9330b6b 100644 --- a/code/SceneCombiner.h +++ b/code/SceneCombiner.h @@ -166,7 +166,7 @@ struct SceneHelper id[0] = 0; } - SceneHelper (aiScene* _scene) + explicit SceneHelper (aiScene* _scene) : scene (_scene) , idlen (0) { diff --git a/code/StdOStreamLogStream.h b/code/StdOStreamLogStream.h index 02bf508af..be1b2c640 100644 --- a/code/StdOStreamLogStream.h +++ b/code/StdOStreamLogStream.h @@ -16,7 +16,7 @@ public: /** @brief Construction from an existing std::ostream * @param _ostream Output stream to be used */ - StdOStreamLogStream(std::ostream& _ostream); + explicit StdOStreamLogStream(std::ostream& _ostream); /** @brief Destructor */ ~StdOStreamLogStream(); diff --git a/code/TinyFormatter.h b/code/TinyFormatter.h index 84ecfb62d..0559102f8 100644 --- a/code/TinyFormatter.h +++ b/code/TinyFormatter.h @@ -97,7 +97,7 @@ public: // being bound to const ref& function parameters. Copying streams is not permitted, though. // This workaround avoids this by manually specifying a copy ctor. #if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) - basic_formatter(const basic_formatter& other) { + explicit basic_formatter(const basic_formatter& other) { underlying << (string)other; } #endif diff --git a/code/UnrealLoader.h b/code/UnrealLoader.h index e9b6c404a..4d087bd78 100644 --- a/code/UnrealLoader.h +++ b/code/UnrealLoader.h @@ -87,7 +87,7 @@ struct TempMat { , numFaces (0) {} - TempMat(const Triangle& in) + explicit TempMat(const Triangle& in) : type ((Unreal::MeshFlags)in.mType) , tex (in.mTextureNum) , numFaces (0) diff --git a/code/XFileHelper.h b/code/XFileHelper.h index cb5d9abb0..1760162ce 100644 --- a/code/XFileHelper.h +++ b/code/XFileHelper.h @@ -129,7 +129,7 @@ struct Mesh std::vector mBones; - Mesh(const std::string &pName = "") { mName = pName; mNumTextures = 0; mNumColorSets = 0; } + explicit Mesh(const std::string &pName = "") { mName = pName; mNumTextures = 0; mNumColorSets = 0; } }; /** Helper structure to represent a XFile frame */ @@ -142,7 +142,7 @@ struct Node std::vector mMeshes; Node() { mParent = NULL; } - Node( Node* pParent) { mParent = pParent; } + explicit Node( Node* pParent) { mParent = pParent; } ~Node() { for( unsigned int a = 0; a < mChildren.size(); a++) diff --git a/code/XFileParser.h b/code/XFileParser.h index e4308a6e2..73426d6a5 100644 --- a/code/XFileParser.h +++ b/code/XFileParser.h @@ -68,7 +68,7 @@ public: /** Constructor. Creates a data structure out of the XFile given in the memory block. * @param pBuffer Null-terminated memory buffer containing the XFile */ - XFileParser( const std::vector& pBuffer); + explicit XFileParser( const std::vector& pBuffer); /** Destructor. Destroys all imported data along with it */ ~XFileParser(); diff --git a/code/irrXMLWrapper.h b/code/irrXMLWrapper.h index 526a04d1b..7eda2f5ae 100644 --- a/code/irrXMLWrapper.h +++ b/code/irrXMLWrapper.h @@ -76,7 +76,7 @@ public: // ---------------------------------------------------------------------------------- //! Construction from an existing IOStream - CIrrXML_IOStreamReader(IOStream* _stream) + explicit CIrrXML_IOStreamReader(IOStream* _stream) : stream (_stream) , t (0) { diff --git a/include/assimp/DefaultLogger.hpp b/include/assimp/DefaultLogger.hpp index 488f39d27..f4282827e 100644 --- a/include/assimp/DefaultLogger.hpp +++ b/include/assimp/DefaultLogger.hpp @@ -135,7 +135,7 @@ private: // ---------------------------------------------------------------------- /** @briefPrivate construction for internal use by create(). * @param severity Logging granularity */ - DefaultLogger(LogSeverity severity); + explicit DefaultLogger(LogSeverity severity); // ---------------------------------------------------------------------- /** @briefDestructor */ diff --git a/include/assimp/Logger.hpp b/include/assimp/Logger.hpp index 7e1c52908..5fc8e7d42 100644 --- a/include/assimp/Logger.hpp +++ b/include/assimp/Logger.hpp @@ -160,7 +160,7 @@ protected: Logger(); /** Construction with a given log severity */ - Logger(LogSeverity severity); + explicit Logger(LogSeverity severity); // ---------------------------------------------------------------------- /** @brief Called as a request to write a specific debug message diff --git a/include/assimp/color4.h b/include/assimp/color4.h index 1e2070b98..f97d9b9d6 100644 --- a/include/assimp/color4.h +++ b/include/assimp/color4.h @@ -59,7 +59,7 @@ public: aiColor4t () : r(), g(), b(), a() {} aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a) : r(_r), g(_g), b(_b), a(_a) {} - aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {} + explicit aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {} aiColor4t (const aiColor4t& o) : r(o.r), g(o.g), b(o.b), a(o.a) {} diff --git a/include/assimp/quaternion.h b/include/assimp/quaternion.h index 34af2c483..d700703d3 100644 --- a/include/assimp/quaternion.h +++ b/include/assimp/quaternion.h @@ -60,7 +60,7 @@ public: : w(pw), x(px), y(py), z(pz) {} /** Construct from rotation matrix. Result is undefined if the matrix is not orthonormal. */ - aiQuaterniont( const aiMatrix3x3t& pRotMatrix); + explicit aiQuaterniont( const aiMatrix3x3t& pRotMatrix); /** Construct from euler angles */ aiQuaterniont( TReal rotx, TReal roty, TReal rotz); @@ -69,7 +69,7 @@ public: aiQuaterniont( aiVector3t axis, TReal angle); /** Construct from a normalized quaternion stored in a vec3 */ - aiQuaterniont( aiVector3t normalized); + explicit aiQuaterniont( aiVector3t normalized); /** Returns a matrix representation of the quaternion */ aiMatrix3x3t GetMatrix() const; diff --git a/include/assimp/scene.h b/include/assimp/scene.h index 2c51eaf79..87cb7a61c 100644 --- a/include/assimp/scene.h +++ b/include/assimp/scene.h @@ -135,7 +135,7 @@ struct aiNode /** Construction from a specific name */ - aiNode(const std::string& name) + explicit aiNode(const std::string& name) // set all members to zero by default : mName(name) , mParent(NULL) diff --git a/include/assimp/types.h b/include/assimp/types.h index 82be2d62f..35129b7a3 100644 --- a/include/assimp/types.h +++ b/include/assimp/types.h @@ -160,7 +160,7 @@ struct aiColor3D #ifdef __cplusplus aiColor3D () : r(0.0f), g(0.0f), b(0.0f) {} aiColor3D (float _r, float _g, float _b) : r(_r), g(_g), b(_b) {} - aiColor3D (float _r) : r(_r), g(_r), b(_r) {} + explicit aiColor3D (float _r) : r(_r), g(_r), b(_r) {} aiColor3D (const aiColor3D& o) : r(o.r), g(o.g), b(o.b) {} /** Component-wise comparison */ From eadc6116c04cfdfdddbf5260629639af8f497047 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 31 Oct 2015 09:43:34 +0100 Subject: [PATCH 33/77] OpenDDLParser: latest greatest. --- code/Q3BSPFileImporter.cpp | 2 +- contrib/openddlparser/code/DDLNode.cpp | 2 +- contrib/openddlparser/code/OpenDDLExport.cpp | 338 ++++++++++++++++-- contrib/openddlparser/code/OpenDDLParser.cpp | 68 ++-- contrib/openddlparser/code/Value.cpp | 49 ++- .../include/openddlparser/OpenDDLCommon.h | 1 + .../include/openddlparser/OpenDDLExport.h | 66 +++- .../include/openddlparser/OpenDDLParser.h | 4 +- .../include/openddlparser/Value.h | 12 + 9 files changed, 466 insertions(+), 76 deletions(-) diff --git a/code/Q3BSPFileImporter.cpp b/code/Q3BSPFileImporter.cpp index c27b0c63c..2526aeb26 100644 --- a/code/Q3BSPFileImporter.cpp +++ b/code/Q3BSPFileImporter.cpp @@ -325,7 +325,7 @@ void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* p matIdx++; } - pScene->mNumMeshes = MeshArray.size(); + pScene->mNumMeshes = static_cast( MeshArray.size() ); if ( pScene->mNumMeshes > 0 ) { pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; diff --git a/contrib/openddlparser/code/DDLNode.cpp b/contrib/openddlparser/code/DDLNode.cpp index d5ff20482..e39634cdc 100644 --- a/contrib/openddlparser/code/DDLNode.cpp +++ b/contrib/openddlparser/code/DDLNode.cpp @@ -117,7 +117,6 @@ const std::string &DDLNode::getType() const { return m_type; } - void DDLNode::setName( const std::string &name ) { m_name = name; } @@ -151,6 +150,7 @@ Property *DDLNode::findPropertyByName( const std::string &name ) { if( ddl_nullptr == m_properties ) { return ddl_nullptr; } + Property *current( m_properties ); while( ddl_nullptr != current ) { int res = strncmp( current->m_key->m_text.m_buffer, name.c_str(), name.size() ); diff --git a/contrib/openddlparser/code/OpenDDLExport.cpp b/contrib/openddlparser/code/OpenDDLExport.cpp index 5a010ea59..ba0138d0c 100644 --- a/contrib/openddlparser/code/OpenDDLExport.cpp +++ b/contrib/openddlparser/code/OpenDDLExport.cpp @@ -22,16 +22,61 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -----------------------------------------------------------------------------------------------*/ #include #include +#include +#include + +#include BEGIN_ODDLPARSER_NS +IOStreamBase::IOStreamBase() +: m_file( ddl_nullptr ) { + // empty +} +IOStreamBase::~IOStreamBase() { + // empty +} + +bool IOStreamBase::open( const std::string &name ) { + m_file = ::fopen( name.c_str(), "a" ); + if (m_file == ddl_nullptr) { + return false; + } + + return true; +} + +bool IOStreamBase::close() { + if (ddl_nullptr == m_file) { + return false; + } + + ::fclose( m_file ); + m_file = ddl_nullptr; + + return true; +} + +void IOStreamBase::write( const std::string &statement ) { + if (ddl_nullptr == m_file) { + return; + } + + ::fwrite( statement.c_str(), sizeof( char ), statement.size(), m_file ); +} + struct DDLNodeIterator { const DDLNode::DllNodeList &m_childs; size_t m_idx; - DDLNodeIterator( const DDLNode::DllNodeList &childs ) - : m_childs( childs ) - , m_idx( 0 ) { + DDLNodeIterator( const DDLNode::DllNodeList &childs ) + : m_childs( childs ) + , m_idx( 0 ) { + // empty + } + + ~DDLNodeIterator() { + // empty } bool getNext( DDLNode **node ) { @@ -45,33 +90,43 @@ struct DDLNodeIterator { } }; -OpenDDLExport::OpenDDLExport() -:m_file( nullptr ) { +static void writeLineEnd( std::string &statement ) { + statement += "\n"; +} +OpenDDLExport::OpenDDLExport( IOStreamBase *stream ) +: m_stream( stream ) { + if (ddl_nullptr == m_stream) { + m_stream = new IOStreamBase(); + } } OpenDDLExport::~OpenDDLExport() { - if( nullptr != m_file ) { - ::fclose( m_file ); - m_file = nullptr; + if (ddl_nullptr != m_stream) { + m_stream->close(); } + delete m_stream; } bool OpenDDLExport::exportContext( Context *ctx, const std::string &filename ) { - if( filename.empty() ) { - return false; - } - if( ddl_nullptr == ctx ) { return false; } DDLNode *root( ctx->m_root ); - if( nullptr == root ) { + if ( ddl_nullptr == root ) { return true; } - return handleNode( root ); + if (!filename.empty()) { + if (!m_stream->open( filename )) { + return false; + } + } + + const bool retValue( handleNode( root ) ); + + return retValue; } bool OpenDDLExport::handleNode( DDLNode *node ) { @@ -85,12 +140,13 @@ bool OpenDDLExport::handleNode( DDLNode *node ) { } DDLNode *current( ddl_nullptr ); DDLNodeIterator it( childs ); + std::string statement; bool success( true ); while( it.getNext( ¤t ) ) { if( ddl_nullptr != current ) { - success |= writeNode( current ); + success |= writeNode( current, statement ); if( !handleNode( current ) ) { - success != false; + success = false; } } } @@ -98,17 +154,257 @@ bool OpenDDLExport::handleNode( DDLNode *node ) { return success; } -bool OpenDDLExport::writeNode( DDLNode *node ) { - bool success( true ); - if( node->hasProperties() ) { - success |= writeProperties( node ); +bool OpenDDLExport::writeToStream( const std::string &statement ) { + if (ddl_nullptr == m_stream ) { + return false; + } + + if ( !statement.empty()) { + m_stream->write( statement ); } return true; } -bool OpenDDLExport::writeProperties( DDLNode *node ) { +bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) { + bool success( true ); + writeNodeHeader( node, statement ); + if (node->hasProperties()) { + success |= writeProperties( node, statement ); + } + writeLineEnd( statement ); + + statement = "}"; + DataArrayList *al( node->getDataArrayList() ); + if ( ddl_nullptr != al ) { + writeValueType( al->m_dataList->m_type, al->m_numItems, statement ); + writeValueArray( al, statement ); + } + Value *v( node->getValue() ); + if (ddl_nullptr != v ) { + writeValueType( v->m_type, 1, statement ); + statement = "{"; + writeLineEnd( statement ); + writeValue( v, statement ); + statement = "}"; + writeLineEnd( statement ); + } + statement = "}"; + writeLineEnd( statement ); + + writeToStream( statement ); + + return true; +} + +bool OpenDDLExport::writeNodeHeader( DDLNode *node, std::string &statement ) { + if (ddl_nullptr == node) { + return false; + } + + statement += node->getType(); + const std::string &name( node->getName() ); + if ( !name.empty() ) { + statement += " "; + statement += "$"; + statement += name; + } + + return true; +} + +bool OpenDDLExport::writeProperties( DDLNode *node, std::string &statement ) { + if ( ddl_nullptr == node ) { + return false; + } + Property *prop( node->getProperties() ); + // if no properties are there, return + if ( ddl_nullptr == prop ) { + return true; + } + + if ( ddl_nullptr != prop ) { + // for instance (attrib = "position", bla=2) + statement += "("; + bool first( true ); + while ( ddl_nullptr != prop ) { + if (!first) { + statement += ", "; + } else { + first = false; + } + statement += std::string( prop->m_key->m_text.m_buffer ); + statement += " = "; + writeValue( prop->m_value, statement ); + prop = prop->m_next; + } + + statement += ")"; + } + + return true; +} + +bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std::string &statement ) { + if ( Value::ddl_types_max == type) { + return false; + } + + const std::string typeStr( getTypeToken( type ) ); + statement += typeStr; + // if we have an array to write + if ( numItems > 1 ) { + statement += "["; + char buffer[ 256 ]; + ::memset( buffer, '\0', 256 * sizeof( char ) ); + sprintf( buffer, "%d", numItems ); + statement += buffer; + statement += "]"; + } + + return true; +} + +bool OpenDDLExport::writeValue( Value *val, std::string &statement ) { + if (ddl_nullptr == val) { + return false; + } + + switch ( val->m_type ) { + case Value::ddl_bool: + if ( true == val->getBool() ) { + statement += "true"; + } else { + statement += "false"; + } + break; + case Value::ddl_int8: + { + std::stringstream stream; + const int i = static_cast( val->getInt8() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_int16: + { + std::stringstream stream; + char buffer[ 256 ]; + ::memset( buffer, '\0', 256 * sizeof( char ) ); + sprintf( buffer, "%d", val->getInt16() ); + statement += buffer; + } + break; + case Value::ddl_int32: + { + std::stringstream stream; + char buffer[ 256 ]; + ::memset( buffer, '\0', 256 * sizeof( char ) ); + const int i = static_cast< int >( val->getInt32() ); + sprintf( buffer, "%d", i ); + statement += buffer; + } + break; + case Value::ddl_int64: + { + std::stringstream stream; + const int i = static_cast< int >( val->getInt64() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_unsigned_int8: + { + std::stringstream stream; + const int i = static_cast< unsigned int >( val->getUnsignedInt8() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_unsigned_int16: + { + std::stringstream stream; + const int i = static_cast< unsigned int >( val->getUnsignedInt16() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_unsigned_int32: + { + std::stringstream stream; + const int i = static_cast< unsigned int >( val->getUnsignedInt32() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_unsigned_int64: + { + std::stringstream stream; + const int i = static_cast< unsigned int >( val->getUnsignedInt64() ); + stream << i; + statement += stream.str(); + } + break; + case Value::ddl_half: + break; + case Value::ddl_float: + { + std::stringstream stream; + stream << val->getFloat(); + statement += stream.str(); + } + break; + case Value::ddl_double: + break; + case Value::ddl_string: + { + std::stringstream stream; + stream << val->getString(); + statement += "\""; + statement += stream.str(); + statement += "\""; + } + break; + case Value::ddl_ref: + break; + case Value::ddl_none: + case Value::ddl_types_max: + default: + break; + } + + return true; +} + +bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) { + if (ddl_nullptr == al) { + return false; + } + + if (0 == al->m_numItems) { + return true; + } + + DataArrayList *nextDataArrayList = al ; + Value *nextValue( nextDataArrayList->m_dataList ); + while (ddl_nullptr != nextDataArrayList) { + if (ddl_nullptr != nextDataArrayList) { + statement += "{ "; + nextValue = nextDataArrayList->m_dataList; + size_t idx( 0 ); + while (ddl_nullptr != nextValue) { + if (idx > 0) { + statement += ", "; + } + writeValue( nextValue, statement ); + nextValue = nextValue->m_next; + idx++; + } + statement += " }"; + } + nextDataArrayList = nextDataArrayList->m_next; + } return true; } diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp index 5505f78b5..dbc90f990 100644 --- a/contrib/openddlparser/code/OpenDDLParser.cpp +++ b/contrib/openddlparser/code/OpenDDLParser.cpp @@ -21,6 +21,7 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -----------------------------------------------------------------------------------------------*/ #include +#include #include #include @@ -67,6 +68,10 @@ namespace Grammar { }; } // Namespace Grammar +const char *getTypeToken( Value::ValueType type ) { + return Grammar::PrimitiveTypeToken[ type ]; +} + static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) { std::stringstream stream; stream << "Invalid token " << *in << ", " << exp << " expected." << std::endl; @@ -211,13 +216,12 @@ bool OpenDDLParser::exportContext( Context *ctx, const std::string &filename ) { return false; } - if( filename.empty() ) { - return false; - } + OpenDDLExport myExporter; + return myExporter.exportContext( ctx, filename ); + return false; } - char *OpenDDLParser::parseNextNode( char *in, char *end ) { in = parseHeader( in, end ); in = parseStructure( in, end ); @@ -227,7 +231,8 @@ char *OpenDDLParser::parseNextNode( char *in, char *end ) { static void dumpId( Identifier *id ) { if( ddl_nullptr != id ) { - std::cout << id->m_text.m_buffer << std::endl; + if ( ddl_nullptr != id->m_text.m_buffer ) { } + std::cout << id->m_text.m_buffer << std::endl; } } @@ -366,7 +371,7 @@ char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) { Value *values( ddl_nullptr ); if( 1 == arrayLen ) { size_t numRefs( 0 ), numValues( 0 ); - in = parseDataList( in, end, &values, numValues, &refs, numRefs ); + in = parseDataList( in, end, type, &values, numValues, &refs, numRefs ); setNodeValues( top(), values ); setNodeReferences( top(), refs ); } else if( arrayLen > 1 ) { @@ -548,7 +553,7 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy while ( in != end ) { in++; if( *in == Grammar::CloseArrayToken[ 0 ] ) { - len = atoi( start ); + len = ::atoi( start ); ok = true; in++; break; @@ -814,7 +819,7 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) { return in; } -char *OpenDDLParser::parseDataList( char *in, char *end, Value **data, size_t &numValues, Reference **refs, size_t &numRefs ) { +char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type, Value **data, size_t &numValues, Reference **refs, size_t &numRefs ) { *data = ddl_nullptr; numValues = numRefs = 0; if( ddl_nullptr == in || in == end ) { @@ -828,21 +833,35 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value **data, size_t &n while( '}' != *in ) { current = ddl_nullptr; in = lookForNextToken( in, end ); - if( isInteger( in, end ) ) { - in = parseIntegerLiteral( in, end, ¤t ); - } else if( isFloat( in, end ) ) { - in = parseFloatingLiteral( in, end, ¤t ); - } else if( isStringLiteral( *in ) ) { - in = parseStringLiteral( in, end, ¤t ); - } else if( isHexLiteral( in, end ) ) { - in = parseHexaLiteral( in, end, ¤t ); - } else { // reference data - std::vector names; - in = parseReference( in, end, names ); - if( !names.empty() ) { - Reference *ref = new Reference( names.size(), &names[ 0 ] ); - *refs = ref; - numRefs = names.size(); + if (Value::ddl_none == type) { + if (isInteger( in, end )) { + in = parseIntegerLiteral( in, end, ¤t ); + } + else if (isFloat( in, end )) { + in = parseFloatingLiteral( in, end, ¤t ); + } + else if (isStringLiteral( *in )) { + in = parseStringLiteral( in, end, ¤t ); + } + else if (isHexLiteral( in, end )) { + in = parseHexaLiteral( in, end, ¤t ); + } + else { // reference data + std::vector names; + in = parseReference( in, end, names ); + if (!names.empty()) { + Reference *ref = new Reference( names.size(), &names[ 0 ] ); + *refs = ref; + numRefs = names.size(); + } + } + } else { + if (Value::ddl_int32 == type) { + in = parseIntegerLiteral( in, end, ¤t ); + } else if (Value::ddl_float == type) { + in = parseFloatingLiteral( in, end, ¤t ); + } else if (Value::ddl_string == type) { + in = parseStringLiteral( in, end, ¤t ); } } @@ -891,7 +910,8 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end, DataArrayList **da do { size_t numRefs( 0 ), numValues( 0 ); currentValue = ddl_nullptr; - in = parseDataList( in, end, ¤tValue, numValues, &refs, numRefs ); + Value::ValueType type( Value::ddl_none ); + in = parseDataList( in, end, type, ¤tValue, numValues, &refs, numRefs ); if( ddl_nullptr != currentValue ) { if( ddl_nullptr == prev ) { *dataList = createDataArrayList( currentValue, numValues ); diff --git a/contrib/openddlparser/code/Value.cpp b/contrib/openddlparser/code/Value.cpp index 52081cea5..067deccb9 100644 --- a/contrib/openddlparser/code/Value.cpp +++ b/contrib/openddlparser/code/Value.cpp @@ -95,7 +95,7 @@ bool Value::Iterator::operator == ( const Iterator &rhs ) const { } Value *Value::Iterator::operator->( ) const { - if( nullptr == m_current ) { + if(ddl_nullptr == m_current ) { return ddl_nullptr; } return m_current; @@ -120,7 +120,6 @@ void Value::setBool( bool value ) { bool Value::getBool() { assert( ddl_bool == m_type ); - return ( *m_data == 1 ); } @@ -141,7 +140,9 @@ void Value::setInt16( int16 value ) { int16 Value::getInt16() { assert( ddl_int16 == m_type ); - return ( int16 ) ( *m_data ); + int16 i; + ::memcpy( &i, m_data, m_size ); + return i; } void Value::setInt32( int32 value ) { @@ -151,16 +152,21 @@ void Value::setInt32( int32 value ) { int32 Value::getInt32() { assert( ddl_int32 == m_type ); - return ( int32 ) ( *m_data ); + int32 i; + ::memcpy( &i, m_data, m_size ); + return i; } void Value::setInt64( int64 value ) { - assert( ddl_int32 == m_type ); + assert( ddl_int64 == m_type ); ::memcpy( m_data, &value, m_size ); } int64 Value::getInt64() { - return ( int64 ) ( *m_data ); + assert( ddl_int64 == m_type ); + int64 i; + ::memcpy( &i, m_data, m_size ); + return i; } void Value::setUnsignedInt8( uint8 value ) { @@ -170,7 +176,9 @@ void Value::setUnsignedInt8( uint8 value ) { uint8 Value::getUnsignedInt8() const { assert( ddl_unsigned_int8 == m_type ); - return ( uint8 ) ( *m_data ); + uint8 i; + ::memcpy( &i, m_data, m_size ); + return i; } void Value::setUnsignedInt16( uint16 value ) { @@ -180,7 +188,9 @@ void Value::setUnsignedInt16( uint16 value ) { uint16 Value::getUnsignedInt16() const { assert( ddl_unsigned_int16 == m_type ); - return ( uint8 ) ( *m_data ); + uint16 i; + ::memcpy( &i, m_data, m_size ); + return i; } void Value::setUnsignedInt32( uint32 value ) { @@ -190,7 +200,9 @@ void Value::setUnsignedInt32( uint32 value ) { uint32 Value::getUnsignedInt32() const { assert( ddl_unsigned_int32 == m_type ); - return ( uint8 ) ( *m_data ); + uint32 i; + ::memcpy( &i, m_data, m_size ); + return i; } void Value::setUnsignedInt64( uint64 value ) { @@ -200,7 +212,9 @@ void Value::setUnsignedInt64( uint64 value ) { uint64 Value::getUnsignedInt64() const { assert( ddl_unsigned_int64 == m_type ); - return ( uint64 ) ( *m_data ); + uint64 i; + ::memcpy( &i, m_data, m_size ); + return i; } void Value::setFloat( float value ) { @@ -226,6 +240,7 @@ void Value::setDouble( double value ) { } double Value::getDouble() const { + assert( ddl_double == m_type ); double v; ::memcpy( &v, m_data, m_size ); return v; @@ -237,6 +252,7 @@ void Value::setString( const std::string &str ) { m_data[ str.size() ] = '\0'; } const char *Value::getString() const { + assert( ddl_string == m_type ); return (const char*) m_data; } @@ -312,22 +328,25 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) { data->m_size = sizeof( bool ); break; case Value::ddl_int8: - data->m_size = sizeof( char ); + data->m_size = sizeof( int8 ); break; case Value::ddl_int16: - data->m_size = sizeof( short ); + data->m_size = sizeof( int16 ); break; case Value::ddl_int32: - data->m_size = sizeof( int ); + data->m_size = sizeof( int32 ); break; case Value::ddl_int64: data->m_size = sizeof( int64 ); break; case Value::ddl_unsigned_int8: - data->m_size = sizeof( unsigned char ); + data->m_size = sizeof( uint8 ); + break; + case Value::ddl_unsigned_int16: + data->m_size = sizeof( uint16 ); break; case Value::ddl_unsigned_int32: - data->m_size = sizeof( unsigned int ); + data->m_size = sizeof( uint32 ); break; case Value::ddl_unsigned_int64: data->m_size = sizeof( uint64 ); diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h index c86c7ce9d..701eb72d6 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h @@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include #include #ifndef _WIN32 # include diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLExport.h b/contrib/openddlparser/include/openddlparser/OpenDDLExport.h index 269296527..170da5bfa 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLExport.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLExport.h @@ -23,26 +23,66 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #pragma once #include +#include BEGIN_ODDLPARSER_NS -/// -/// @ingroup OpenDDLParser -/// @brief This class represents the OpenDDLExporter. -/// -class DLL_ODDLPARSER_EXPORT OpenDDLExport { +//------------------------------------------------------------------------------------------------- +/// @ingroup IOStreamBase +/// @brief This class represents the stream to write out. +//------------------------------------------------------------------------------------------------- +class DLL_ODDLPARSER_EXPORT IOStreamBase { public: - OpenDDLExport(); - ~OpenDDLExport(); - bool exportContext( Context *ctx, const std::string &filename ); - bool handleNode( DDLNode *node ); - -protected: - bool writeNode( DDLNode *node ); - bool writeProperties( DDLNode *node ); + IOStreamBase(); + virtual ~IOStreamBase(); + virtual bool open( const std::string &anme ); + virtual bool close(); + virtual void write( const std::string &statement ); private: FILE *m_file; }; +//------------------------------------------------------------------------------------------------- +/// +/// @ingroup OpenDDLParser +/// @brief This class represents the OpenDDLExporter. +/// +//------------------------------------------------------------------------------------------------- +class DLL_ODDLPARSER_EXPORT OpenDDLExport { +public: + /// @brief The class constructor + OpenDDLExport( IOStreamBase *stream = ddl_nullptr ); + + /// @brief The class destructor. + ~OpenDDLExport(); + + /// @brief Export the data of a parser context. + /// @param ctx [in] Pointer to the context. + /// @param filename [in] The filename for the export. + /// @return True in case of success, false in case of an error. + bool exportContext( Context *ctx, const std::string &filename ); + + /// @brief Handles a node export. + /// @param node [in] The node to handle with. + /// @return True in case of success, false in case of an error. + bool handleNode( DDLNode *node ); + + /// @brief Writes the statement to the stream. + /// @param statement [in] The content to write. + /// @return True in case of success, false in case of an error. + bool writeToStream( const std::string &statement ); + +protected: + bool writeNode( DDLNode *node, std::string &statement ); + bool writeNodeHeader( DDLNode *node, std::string &statement ); + bool writeProperties( DDLNode *node, std::string &statement ); + bool writeValueType( Value::ValueType type, size_t numItems, std::string &statement ); + bool writeValue( Value *val, std::string &statement ); + bool writeValueArray( DataArrayList *al, std::string &statement ); + +private: + IOStreamBase *m_stream; +}; + END_ODDLPARSER_NS diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParser.h b/contrib/openddlparser/include/openddlparser/OpenDDLParser.h index 5c33895b6..22b1f7fbb 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLParser.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLParser.h @@ -80,6 +80,8 @@ enum LogSeverity { ddl_error_msg ///< Parser errors }; +DLL_ODDLPARSER_EXPORT const char *getTypeToken( Value::ValueType type ); + //------------------------------------------------------------------------------------------------- /// @class OpenDDLParser /// @ingroup OpenDDLParser @@ -168,7 +170,7 @@ public: // parser helpers static char *parseStringLiteral( char *in, char *end, Value **stringData ); static char *parseHexaLiteral( char *in, char *end, Value **data ); static char *parseProperty( char *in, char *end, Property **prop ); - static char *parseDataList( char *in, char *end, Value **data, size_t &numValues, Reference **refs, size_t &numRefs ); + static char *parseDataList( char *in, char *end, Value::ValueType type, Value **data, size_t &numValues, Reference **refs, size_t &numRefs ); static char *parseDataArrayList( char *in, char *end, DataArrayList **dataList ); static const char *getVersion(); diff --git a/contrib/openddlparser/include/openddlparser/Value.h b/contrib/openddlparser/include/openddlparser/Value.h index 00b644540..af5ebe7bf 100644 --- a/contrib/openddlparser/include/openddlparser/Value.h +++ b/contrib/openddlparser/include/openddlparser/Value.h @@ -151,11 +151,23 @@ public: size_t m_size; unsigned char *m_data; Value *m_next; + +private: + Value &operator =( const Value & ); + Value( const Value & ); }; +///------------------------------------------------------------------------------------------------ +/// @brief This class implements the value allocator. +///------------------------------------------------------------------------------------------------ struct DLL_ODDLPARSER_EXPORT ValueAllocator { static Value *allocPrimData( Value::ValueType type, size_t len = 1 ); static void releasePrimData( Value **data ); + +private: + ValueAllocator(); + ValueAllocator( const ValueAllocator & ); + ValueAllocator &operator = ( const ValueAllocator & ); }; END_ODDLPARSER_NS From 6be8df5fde8760298d793507921b0a7143f767fd Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 1 Nov 2015 12:20:35 +0100 Subject: [PATCH 34/77] Boost::tuple: fix compiler-specifc test. --- test/unit/utNoBoostTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/utNoBoostTest.cpp b/test/unit/utNoBoostTest.cpp index a8c2f1567..d584e05c2 100644 --- a/test/unit/utNoBoostTest.cpp +++ b/test/unit/utNoBoostTest.cpp @@ -36,12 +36,12 @@ TEST(NoBoostTest, Tuple) { EXPECT_EQ(4U, first.get<1>()); EXPECT_EQ(4U, first.get<2>()); - boost::tuple second; + boost::tuple second; bool b = second.get<3>(); - EXPECT_FALSE(b); - // check empty tuple, ignore compile warning + // check empty tuple boost::tuple<> third; + third; // FIXME: Explicit conversion not really required yet boost::tuple last = From 95c20cb5abcbd6da802066943c421f6c0d23addd Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 1 Nov 2015 13:48:55 +0100 Subject: [PATCH 35/77] Collada exporter: fix invalid access to already release scene after reimporting exported scene. --- test/unit/utColladaExportCamera.cpp | 46 +++++++++++++++++++---------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/test/unit/utColladaExportCamera.cpp b/test/unit/utColladaExportCamera.cpp index 8735c626e..ea9afe15c 100644 --- a/test/unit/utColladaExportCamera.cpp +++ b/test/unit/utColladaExportCamera.cpp @@ -49,32 +49,48 @@ TEST_F(ColladaExportCamera, testExportCamera) EXPECT_EQ(AI_SUCCESS,ex->Export(pTest,"collada",file)); - + const unsigned int origNumCams( pTest->mNumCameras ); + float *origFOV = new float[ origNumCams ]; + float *orifClipPlaneNear = new float[ origNumCams ]; + float *orifClipPlaneFar = new float[ origNumCams ]; + aiString *names = new aiString[ origNumCams ]; + aiVector3D *pos = new aiVector3D[ origNumCams ]; + for (size_t i = 0; i < origNumCams; i++) { + const aiCamera *orig = pTest->mCameras[ i ]; + origFOV[ i ] = orig->mHorizontalFOV; + orifClipPlaneNear[ i ] = orig->mClipPlaneNear; + orifClipPlaneFar[ i ] = orig->mClipPlaneFar; + names[ i ] = orig->mName; + pos[ i ] = orig->mPosition; + } const aiScene* imported = im->ReadFile(file,0); ASSERT_TRUE(imported!=NULL); - EXPECT_TRUE(imported->HasCameras()); - EXPECT_EQ(pTest->mNumCameras,imported->mNumCameras); + EXPECT_TRUE( imported->HasCameras() ); + EXPECT_EQ( origNumCams, imported->mNumCameras ); - for(size_t i=0; i< pTest->mNumCameras;i++){ + for(size_t i=0; i< imported->mNumCameras;i++){ + //const aiCamera *orig = pTest->mCameras[ i ]; + const aiCamera *read = imported->mCameras[ i ]; - const aiCamera *orig = pTest->mCameras[i]; - const aiCamera *read = imported->mCameras[i]; + EXPECT_TRUE( names[ i ] == read->mName ); + EXPECT_FLOAT_EQ( origFOV[ i ],read->mHorizontalFOV ); + EXPECT_FLOAT_EQ( orifClipPlaneNear[ i ], read->mClipPlaneNear); + EXPECT_FLOAT_EQ( orifClipPlaneFar[ i ], read->mClipPlaneFar); - EXPECT_TRUE(orig->mName==read->mName); - EXPECT_FLOAT_EQ(orig->mHorizontalFOV,read->mHorizontalFOV); - EXPECT_FLOAT_EQ(orig->mClipPlaneNear,read->mClipPlaneNear); - EXPECT_FLOAT_EQ(orig->mClipPlaneFar,read->mClipPlaneFar); - - EXPECT_FLOAT_EQ(orig->mPosition.x,read->mPosition.x); - EXPECT_FLOAT_EQ(orig->mPosition.y,read->mPosition.y); - EXPECT_FLOAT_EQ(orig->mPosition.z,read->mPosition.z); + EXPECT_FLOAT_EQ( pos[ i ].x,read->mPosition.x); + EXPECT_FLOAT_EQ( pos[ i ].y,read->mPosition.y); + EXPECT_FLOAT_EQ( pos[ i ].z,read->mPosition.z); } + delete [] origFOV; + delete [] orifClipPlaneNear; + delete [] orifClipPlaneFar; + delete [] names; + delete [] pos; } - #endif From c642d9f25ed3f894340f513135f5b71bd7bbf106 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 1 Nov 2015 15:15:39 +0100 Subject: [PATCH 36/77] Collada exporter: fix access violation. --- test/unit/utColladaExportCamera.cpp | 2 +- test/unit/utColladaExportLight.cpp | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/test/unit/utColladaExportCamera.cpp b/test/unit/utColladaExportCamera.cpp index ea9afe15c..41a4dce3a 100644 --- a/test/unit/utColladaExportCamera.cpp +++ b/test/unit/utColladaExportCamera.cpp @@ -71,7 +71,6 @@ TEST_F(ColladaExportCamera, testExportCamera) EXPECT_EQ( origNumCams, imported->mNumCameras ); for(size_t i=0; i< imported->mNumCameras;i++){ - //const aiCamera *orig = pTest->mCameras[ i ]; const aiCamera *read = imported->mCameras[ i ]; EXPECT_TRUE( names[ i ] == read->mName ); @@ -83,6 +82,7 @@ TEST_F(ColladaExportCamera, testExportCamera) EXPECT_FLOAT_EQ( pos[ i ].y,read->mPosition.y); EXPECT_FLOAT_EQ( pos[ i ].z,read->mPosition.z); } + delete [] origFOV; delete [] orifClipPlaneNear; delete [] orifClipPlaneFar; diff --git a/test/unit/utColladaExportLight.cpp b/test/unit/utColladaExportLight.cpp index ee17b77e0..7c4d2edef 100644 --- a/test/unit/utColladaExportLight.cpp +++ b/test/unit/utColladaExportLight.cpp @@ -47,6 +47,11 @@ TEST_F(ColladaExportLight, testExportLight) ASSERT_TRUE(pTest!=NULL); ASSERT_TRUE(pTest->HasLights()); + const unsigned int origNumLights( pTest->mNumLights ); + aiLight *origLights = new aiLight[ origNumLights ]; + for (size_t i = 0; i < origNumLights; i++) { + origLights[ i ] = *(pTest->mLights[ i ]); + } EXPECT_EQ(AI_SUCCESS,ex->Export(pTest,"collada",file)); EXPECT_EQ(AI_SUCCESS,ex->Export(pTest,"collada","lightsExp.dae")); @@ -56,11 +61,11 @@ TEST_F(ColladaExportLight, testExportLight) ASSERT_TRUE(imported!=NULL); EXPECT_TRUE(imported->HasLights()); - EXPECT_EQ(pTest->mNumLights,imported->mNumLights); - + EXPECT_EQ( origNumLights,imported->mNumLights ); for(size_t i=0; i< pTest->mNumLights;i++){ - const aiLight *orig = pTest->mLights[i]; + const aiLight *orig = &origLights[ i ]; + const aiLight *read = imported->mLights[i]; EXPECT_TRUE(orig->mName==read->mName); From 97d5b1c8220e72145b719955936f4d0ae155786f Mon Sep 17 00:00:00 2001 From: Dave Jarvis Date: Sun, 1 Nov 2015 15:57:29 -0800 Subject: [PATCH 37/77] Unix build instructions Added actual instructions rather than telling people to go read about where to find the instructions to read. Note that simple Windows instructions should be added as well. --- INSTALL | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/INSTALL b/INSTALL index 563fda397..6cdf27140 100644 --- a/INSTALL +++ b/INSTALL @@ -33,13 +33,7 @@ CMake is the preferred build system for Assimp. The minimum required version is 2.6. If you don't have it yet, downloads for CMake can be found on http://www.cmake.org/. -Building Assimp with CMake is 'business as usual' if you've used CMake -before. All steps can be done either on the command line / shell or -by using the CMake GUI tool, the choice is up to you. - -First, invoke CMake to generate build files for a particular -toolchain (for standard GNU makefiles: cmake -G 'Unix Makefiles'). -Afterwards, use the generated build files to perform the actual -build. - +For Unix: +1. cmake -G 'Unix Makefiles' +2. make From 0ea46825867fc0f9f0a54b59e0b929ff3d31e6b7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 2 Nov 2015 21:09:26 +0100 Subject: [PATCH 38/77] Collada Export test: fix unit test for lightsCollada Export test: fix unit test for lights.. --- test/unit/utColladaExportCamera.cpp | 2 +- test/unit/utColladaExportLight.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/unit/utColladaExportCamera.cpp b/test/unit/utColladaExportCamera.cpp index 41a4dce3a..0d864553b 100644 --- a/test/unit/utColladaExportCamera.cpp +++ b/test/unit/utColladaExportCamera.cpp @@ -74,7 +74,7 @@ TEST_F(ColladaExportCamera, testExportCamera) const aiCamera *read = imported->mCameras[ i ]; EXPECT_TRUE( names[ i ] == read->mName ); - EXPECT_FLOAT_EQ( origFOV[ i ],read->mHorizontalFOV ); + EXPECT_NEAR( origFOV[ i ],read->mHorizontalFOV, 0.0001f ); EXPECT_FLOAT_EQ( orifClipPlaneNear[ i ], read->mClipPlaneNear); EXPECT_FLOAT_EQ( orifClipPlaneFar[ i ], read->mClipPlaneFar); diff --git a/test/unit/utColladaExportLight.cpp b/test/unit/utColladaExportLight.cpp index 7c4d2edef..95c44f7bc 100644 --- a/test/unit/utColladaExportLight.cpp +++ b/test/unit/utColladaExportLight.cpp @@ -49,7 +49,9 @@ TEST_F(ColladaExportLight, testExportLight) const unsigned int origNumLights( pTest->mNumLights ); aiLight *origLights = new aiLight[ origNumLights ]; + std::vector origNames; for (size_t i = 0; i < origNumLights; i++) { + origNames.push_back( pTest->mLights[ i ]->mName.C_Str() ); origLights[ i ] = *(pTest->mLights[ i ]); } @@ -62,17 +64,17 @@ TEST_F(ColladaExportLight, testExportLight) EXPECT_TRUE(imported->HasLights()); EXPECT_EQ( origNumLights,imported->mNumLights ); - for(size_t i=0; i< pTest->mNumLights;i++){ + for(size_t i=0; i< origNumLights; i++){ const aiLight *orig = &origLights[ i ]; const aiLight *read = imported->mLights[i]; - EXPECT_TRUE(orig->mName==read->mName); + EXPECT_EQ(0,strncmp(origNames[ i ].c_str(),read->mName.C_Str(), origNames[ i ].size() ) ); EXPECT_EQ(orig->mType,read->mType); EXPECT_FLOAT_EQ(orig->mAttenuationConstant,read->mAttenuationConstant); EXPECT_FLOAT_EQ(orig->mAttenuationLinear,read->mAttenuationLinear); - EXPECT_FLOAT_EQ(orig->mAttenuationQuadratic,read->mAttenuationQuadratic); + EXPECT_NEAR(orig->mAttenuationQuadratic,read->mAttenuationQuadratic, 0.001f); EXPECT_FLOAT_EQ(orig->mColorAmbient.r,read->mColorAmbient.r); EXPECT_FLOAT_EQ(orig->mColorAmbient.g,read->mColorAmbient.g); @@ -89,6 +91,7 @@ TEST_F(ColladaExportLight, testExportLight) EXPECT_NEAR(orig->mAngleInnerCone,read->mAngleInnerCone,0.001); EXPECT_NEAR(orig->mAngleOuterCone,read->mAngleOuterCone,0.001); } + delete [] origLights; } From 54c77e78b3ce8d5e7dc7674dad4a8dca7e0ad2b4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 3 Nov 2015 10:51:13 +0100 Subject: [PATCH 39/77] Update INSTALL Add missing win32-build info and fix one missing statement for unix-build. --- INSTALL | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index 6cdf27140..3baaddc4a 100644 --- a/INSTALL +++ b/INSTALL @@ -35,5 +35,10 @@ http://www.cmake.org/. For Unix: -1. cmake -G 'Unix Makefiles' +1. cmake CMakeLists.txt -G 'Unix Makefiles' 2. make + +For Windows: +1. Open a command prompt +2. cmake CMakeLists.txt +2. Open your default IDE and build it From 2fa797949b0345738ececb44bdf853ca5efb070e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 3 Nov 2015 17:12:56 +0100 Subject: [PATCH 40/77] Update Readme.md The 3000. commit :-) --- Readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Readme.md b/Readme.md index 1a99bf873..c051860ac 100644 --- a/Readme.md +++ b/Readme.md @@ -128,3 +128,7 @@ Our license is based on the modified, __3-clause BSD__-License. An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp. For the legal details, see the `LICENSE` file. + +### Why this name ### + +Sorry, we're germans :-), no english native speakers ... From 655cb65ab2b91714f06d058a70658d42df0153dd Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 3 Nov 2015 19:43:02 +0100 Subject: [PATCH 41/77] Version: increase version from 3.1.1 to 3.2. --- code/Version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Version.cpp b/code/Version.cpp index c17069695..c61043567 100644 --- a/code/Version.cpp +++ b/code/Version.cpp @@ -6,7 +6,7 @@ #include "ScenePrivate.h" static const unsigned int MajorVersion = 3; -static const unsigned int MinorVersion = 1; +static const unsigned int MinorVersion = 2; // -------------------------------------------------------------------------------- // Legal information string - dont't remove this. From c318d648ff73aa2e32b783709d69740ac3e8c072 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 3 Nov 2015 19:47:37 +0100 Subject: [PATCH 42/77] CMake: set version number to 3.2 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbb7bd641..bc4c9cdc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ endif(NOT BUILD_SHARED_LIBS) # Define here the needed parameters set (ASSIMP_VERSION_MAJOR 3) -set (ASSIMP_VERSION_MINOR 1) -set (ASSIMP_VERSION_PATCH 1) # subversion revision? +set (ASSIMP_VERSION_MINOR 2) +set (ASSIMP_VERSION_PATCH 0) # subversion revision? set (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}) set (ASSIMP_SOVERSION 3) set (PROJECT_VERSION "${ASSIMP_VERSION}") From 02ad37663108e45977de0f630ef9556ae1a3f107 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 7 Nov 2015 10:00:55 +0100 Subject: [PATCH 43/77] assimp/issues/685: add test for correct usage. --- include/assimp/matrix4x4.inl | 14 ++++-- test/CMakeLists.txt | 1 + test/unit/utMatrix4x4.cpp | 87 ++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 test/unit/utMatrix4x4.cpp diff --git a/include/assimp/matrix4x4.inl b/include/assimp/matrix4x4.inl index c1640c290..8b4b2a429 100644 --- a/include/assimp/matrix4x4.inl +++ b/include/assimp/matrix4x4.inl @@ -238,16 +238,22 @@ inline aiMatrix4x4t& aiMatrix4x4t::Inverse() // ---------------------------------------------------------------------------------------- template -inline TReal* aiMatrix4x4t::operator[](unsigned int p_iIndex) -{ +inline TReal* aiMatrix4x4t::operator[](unsigned int p_iIndex) { + if (p_iIndex > 3) { + return NULL; + } + // XXX this is UB. Has been for years. The fact that it works now does not make it better. return &this->a1 + p_iIndex * 4; } // ---------------------------------------------------------------------------------------- template -inline const TReal* aiMatrix4x4t::operator[](unsigned int p_iIndex) const -{ +inline const TReal* aiMatrix4x4t::operator[](unsigned int p_iIndex) const { + if (p_iIndex > 3) { + return NULL; + } + // XXX same return &this->a1 + p_iIndex * 4; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d3bd490e8..cbb1f7c77 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -28,6 +28,7 @@ SET( TEST_SRCS unit/utJoinVertices.cpp unit/utLimitBoneWeights.cpp unit/utMaterialSystem.cpp + unit/utMatrix4x4.cpp unit/utPretransformVertices.cpp unit/utRemoveComments.cpp unit/utRemoveComponent.cpp diff --git a/test/unit/utMatrix4x4.cpp b/test/unit/utMatrix4x4.cpp new file mode 100644 index 000000000..eefbc251c --- /dev/null +++ b/test/unit/utMatrix4x4.cpp @@ -0,0 +1,87 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" + +using namespace Assimp; + +class utMatrix4x4Test : public ::testing::Test { + +}; + +TEST_F( utMatrix4x4Test, IndexOperatorTest ) { + aiMatrix4x4 m; + float *a0 = m[ 0 ]; + EXPECT_FLOAT_EQ( 1.0f, *a0 ); + float *a1 = a0+1; + EXPECT_FLOAT_EQ( 0.0f, *a1 ); + float *a2 = a0 + 2; + EXPECT_FLOAT_EQ( 0.0f, *a2 ); + float *a3 = a0 + 3; + EXPECT_FLOAT_EQ( 0.0f, *a3 ); + + float *a4 = m[ 1 ]; + EXPECT_FLOAT_EQ( 0.0f, *a4 ); + float *a5 = a4 + 1; + EXPECT_FLOAT_EQ( 1.0f, *a5 ); + float *a6 = a4 + 2; + EXPECT_FLOAT_EQ( 0.0f, *a6 ); + float *a7 = a4 + 3; + EXPECT_FLOAT_EQ( 0.0f, *a7 ); + + float *a8 = m[ 2 ]; + EXPECT_FLOAT_EQ( 0.0f, *a8 ); + float *a9 = a8 + 1; + EXPECT_FLOAT_EQ( 0.0f, *a9 ); + float *a10 = a8 + 2; + EXPECT_FLOAT_EQ( 1.0f, *a10 ); + float *a11 = a8 + 3; + EXPECT_FLOAT_EQ( 0.0f, *a11 ); + + float *a12 = m[ 3 ]; + EXPECT_FLOAT_EQ( 0.0f, *a12 ); + float *a13 = a12 + 1; + EXPECT_FLOAT_EQ( 0.0f, *a13 ); + float *a14 = a12 + 2; + EXPECT_FLOAT_EQ( 0.0f, *a14 ); + float *a15 = a12 + 3; + EXPECT_FLOAT_EQ( 1.0f, *a15 ); +} \ No newline at end of file From e6ac1ed66aaba7e90dc265da4b2915a21b0ce16c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 8 Nov 2015 20:29:05 +0100 Subject: [PATCH 44/77] glTF-Importer: add files. --- code/glTFImporter.cpp | 78 +++++++++++++++++++++++++++++++++++++++ code/glTFImporter.h | 62 +++++++++++++++++++++++++++++++ test/unit/utMatrix4x4.cpp | 8 +++- 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 code/glTFImporter.cpp create mode 100644 code/glTFImporter.h diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp new file mode 100644 index 000000000..ece3ec19c --- /dev/null +++ b/code/glTFImporter.cpp @@ -0,0 +1,78 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#include "glTFImporter.h" + +namespace Assimp { + + static const aiImporterDesc desc = { + "glTF Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour, + 0, + 0, + 0, + 0, + "gltf" + }; + +glTFImporter::glTFImporter() +: BaseImporter() { + +} + +glTFImporter::~glTFImporter() { + +} + +bool glTFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const { + return false; +} + +const aiImporterDesc* glTFImporter::GetInfo() const { + return &desc; +} + +void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) { + +} + +} diff --git a/code/glTFImporter.h b/code/glTFImporter.h new file mode 100644 index 000000000..dc13c8a17 --- /dev/null +++ b/code/glTFImporter.h @@ -0,0 +1,62 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef AI_GLTFIMPORTER_H_INC +#define AI_GLTFIMPORTER_H_INC + +#include "BaseImporter.h" + +namespace Assimp { + +class glTFImporter : public BaseImporter { +public: + glTFImporter(); + virtual ~glTFImporter(); + virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const; + +protected: + virtual const aiImporterDesc* GetInfo() const; + virtual void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler ); +}; + +} // Namespace assimp + +#endif // AI_GLTFIMPORTER_H_INC + diff --git a/test/unit/utMatrix4x4.cpp b/test/unit/utMatrix4x4.cpp index eefbc251c..43c6cbb48 100644 --- a/test/unit/utMatrix4x4.cpp +++ b/test/unit/utMatrix4x4.cpp @@ -47,7 +47,13 @@ class utMatrix4x4Test : public ::testing::Test { }; -TEST_F( utMatrix4x4Test, IndexOperatorTest ) { +TEST_F( utMatrix4x4Test, badIndexOperatorTest ) { + aiMatrix4x4 m; + float *a0 = m[ 4 ]; + EXPECT_EQ( NULL, a0 ); +} + +TEST_F( utMatrix4x4Test, indexOperatorTest ) { aiMatrix4x4 m; float *a0 = m[ 0 ]; EXPECT_FLOAT_EQ( 1.0f, *a0 ); From 756cfd4f74b866e3183caede69daa8c105b73bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Fri, 13 Nov 2015 22:33:20 +0100 Subject: [PATCH 45/77] fix compilation on BigEndian cannot pass a function by reference where an lvalue is expected (only applies to bigendian, where a macro expands to a byteswap function) Closes https://github.com/assimp/assimp/issues/613 --- code/Bitmap.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/Bitmap.cpp b/code/Bitmap.cpp index 13ec37204..829fd027b 100644 --- a/code/Bitmap.cpp +++ b/code/Bitmap.cpp @@ -84,7 +84,12 @@ namespace Assimp { template inline std::size_t Copy(uint8_t* data, T& field) { +#ifdef AI_BUILD_BIG_ENDIAN + T field_swapped=AI_BE(field); + std::memcpy(data, &field_swapped, sizeof(field)); return sizeof(field); +#else std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field); +#endif } void Bitmap::WriteHeader(Header& header, IOStream* file) { From 989e8af3fb573d4373baf6685543bef50ad6b20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Fri, 13 Nov 2015 22:33:53 +0100 Subject: [PATCH 46/77] fix argument check for assimp cmdline tool `assimp cmpdump` expects two files as arguments. so we need to check for at least 2 extra arguments (rather than only check for !<1 and access both) --- tools/assimp_cmd/CompareDump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/assimp_cmd/CompareDump.cpp b/tools/assimp_cmd/CompareDump.cpp index 8739c9364..f33d8f91c 100644 --- a/tools/assimp_cmd/CompareDump.cpp +++ b/tools/assimp_cmd/CompareDump.cpp @@ -881,7 +881,7 @@ int Assimp_CompareDump (const char* const* params, unsigned int num) } // assimp cmpdump actual expected - if (num < 1) { + if (num < 2) { std::cout << "assimp cmpdump: Invalid number of arguments. " "See \'assimp cmpdump --help\'\r\n" << std::endl; return 1; From 7806e991d98a657cca980a5dba5baf38fea7138d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Fri, 13 Nov 2015 23:01:49 +0100 Subject: [PATCH 47/77] Convert Windows-1252 charset to UTF-8 Windows-1252, seriously? (this hard-to-detect weirdo charset really makes some problems with some cmdline text-tool) --- contrib/clipper/clipper.cpp | 2 +- contrib/clipper/clipper.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/clipper/clipper.cpp b/contrib/clipper/clipper.cpp index b2316ccd5..c8c62bc2a 100644 --- a/contrib/clipper/clipper.cpp +++ b/contrib/clipper/clipper.cpp @@ -26,7 +26,7 @@ * Paper no. DETC2005-85513 pp. 565-575 * * ASME 2005 International Design Engineering Technical Conferences * * and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24–28, 2005 , Long Beach, California, USA * +* September 24–28, 2005 , Long Beach, California, USA * * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * * * *******************************************************************************/ diff --git a/contrib/clipper/clipper.hpp b/contrib/clipper/clipper.hpp index f6f196d0d..3d6510dff 100644 --- a/contrib/clipper/clipper.hpp +++ b/contrib/clipper/clipper.hpp @@ -26,7 +26,7 @@ * Paper no. DETC2005-85513 pp. 565-575 * * ASME 2005 International Design Engineering Technical Conferences * * and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24–28, 2005 , Long Beach, California, USA * +* September 24–28, 2005 , Long Beach, California, USA * * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * * * *******************************************************************************/ From 40ee5753224f037710ad513f453abd7e11c60467 Mon Sep 17 00:00:00 2001 From: Danke Xie Date: Sun, 15 Nov 2015 13:45:54 -0800 Subject: [PATCH 48/77] Add new light type 'ambient' to match light.h --- port/jassimp/jassimp/src/jassimp/AiLightType.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/port/jassimp/jassimp/src/jassimp/AiLightType.java b/port/jassimp/jassimp/src/jassimp/AiLightType.java index 5df38763c..ec3c39b02 100644 --- a/port/jassimp/jassimp/src/jassimp/AiLightType.java +++ b/port/jassimp/jassimp/src/jassimp/AiLightType.java @@ -70,9 +70,20 @@ public enum AiLightType { * direction it is pointing to. A good example for a spot light is a light * spot in sport arenas. */ - SPOT(0x3); + SPOT(0x3), + + + /** + * The generic light level of the world, including the bounces of all other + * lightsources.

+ * + * Typically, there's at most one ambient light in a scene. + * This light type doesn't have a valid position, direction, or + * other properties, just a color. + */ + AMBIENT(0x4); + - /** * Utility method for converting from c/c++ based integer enums to java * enums.

From 57d7085fb8472a03048134eb56454a9c30943c34 Mon Sep 17 00:00:00 2001 From: Danke Xie Date: Sun, 15 Nov 2015 22:48:17 -0800 Subject: [PATCH 49/77] Fix AndroidJNI header path in CMakelists.txt --- code/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 3d19bf0ef..2b7bcec7b 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -769,7 +769,7 @@ INSTALL( TARGETS assimp 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) - INSTALL(FILES ${HEADER_PATH}/../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h + INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} COMPONENT assimp-dev) endif(ASSIMP_ANDROID_JNIIOSYSTEM) From 24b68b1e3d6423994dddd21a4dd38f2dc3d63ece Mon Sep 17 00:00:00 2001 From: Danke Xie Date: Thu, 19 Nov 2015 03:41:26 -0800 Subject: [PATCH 50/77] Support instance_image in Collada 1.5 files The tag in sampler2D elements is not expected by ColladaParser. This patch parses the instance_image element and gets the image ID. --- code/ColladaParser.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index cdc3cedeb..b239dbe88 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -1509,7 +1509,7 @@ void ColladaParser::ReadEffectParam( Collada::EffectParam& pParam) // don't care for remaining stuff SkipElement( "surface"); } - else if( IsElement( "sampler2D")) + else if( IsElement( "sampler2D") && (FV_1_4_n == mFormat || FV_1_3_n == mFormat)) { // surface ID is given inside tags TestOpening( "source"); @@ -1520,6 +1520,19 @@ void ColladaParser::ReadEffectParam( Collada::EffectParam& pParam) // don't care for remaining stuff SkipElement( "sampler2D"); + } + else if( IsElement( "sampler2D")) + { + // surface ID is given inside tags + TestOpening( "instance_image"); + int attrURL = GetAttribute("url"); + const char* url = mReader->getAttributeValue( attrURL); + if( url[0] != '#') + ThrowException( "Unsupported URL format in instance_image"); + url++; + pParam.mType = Param_Sampler; + pParam.mReference = url; + SkipElement( "sampler2D"); } else { // ignore unknown element From f94bc8d66e71dbf5427d4af1a063ed6537eab772 Mon Sep 17 00:00:00 2001 From: Otger Date: Mon, 23 Nov 2015 19:49:54 +0100 Subject: [PATCH 51/77] Initial support for FBX embedded textures --- code/FBXConverter.cpp | 61 ++++++++++++++++++++++++++++++ code/FBXDocument.cpp | 3 ++ code/FBXDocument.h | 62 ++++++++++++++++++++++++++++++ code/FBXImportSettings.h | 4 ++ code/FBXImporter.cpp | 1 + code/FBXMaterial.cpp | 81 ++++++++++++++++++++++++++++++++++++++++ include/assimp/config.h | 9 +++++ 7 files changed, 221 insertions(+) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index e0c6b9ca2..21cb8055d 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXUtil.h" #include "FBXProperties.h" #include "FBXImporter.h" +#include "StringComparison.h" #include "../include/assimp/scene.h" #include #include @@ -148,6 +149,7 @@ public: std::for_each(animations.begin(),animations.end(),Util::delete_fun()); std::for_each(lights.begin(),lights.end(),Util::delete_fun()); std::for_each(cameras.begin(),cameras.end(),Util::delete_fun()); + std::for_each(textures.begin(),textures.end(),Util::delete_fun()); } @@ -1449,6 +1451,36 @@ private: return static_cast(materials.size() - 1); } + // ------------------------------------------------------------------------------------------------ + // Video -> aiTexture + unsigned int ConvertVideo(const Video& video) + { + // generate empty output texture + aiTexture* out_tex = new aiTexture(); + textures.push_back(out_tex); + + // assuming the texture is compressed + out_tex->mWidth = static_cast(video.ContentLength()); // total data size + out_tex->mHeight = 0; // fixed to 0 + + // steal the data from the Video to avoid an additional copy + out_tex->pcData = reinterpret_cast( const_cast(video).RelinquishContent() ); + + // try to extract a hint from the file extension + const std::string& filename = video.FileName().empty() ? video.RelativeFilename() : video.FileName(); + std::string ext = BaseImporter::GetExtension(filename); + + if(ext == "jpeg") { + ext = "jpg"; + } + + if(ext.size() <= 3) { + memcpy(out_tex->achFormatHint, ext.c_str(), ext.size()); + } + + return static_cast(textures.size() - 1); + } + // ------------------------------------------------------------------------------------------------ void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, @@ -1466,6 +1498,24 @@ private: aiString path; path.Set(tex->RelativeFilename()); + const Video* media = tex->Media(); + if(media != 0) { + unsigned int index; + + VideoMap::const_iterator it = textures_converted.find(media); + if(it != textures_converted.end()) { + index = (*it).second; + } + else { + index = ConvertVideo(*media); + textures_converted[media] = index; + } + + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) + path.data[0] = '*'; + path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); + } + out_mat->AddProperty(&path,_AI_MATKEY_TEXTURE_BASE,target,0); aiUVTransform uvTrafo; @@ -3024,6 +3074,13 @@ private: std::swap_ranges(cameras.begin(),cameras.end(),out->mCameras); } + + if(textures.size()) { + out->mTextures = new aiTexture*[textures.size()](); + out->mNumTextures = static_cast(textures.size()); + + std::swap_ranges(textures.begin(),textures.end(),out->mTextures); + } } @@ -3037,10 +3094,14 @@ private: std::vector animations; std::vector lights; std::vector cameras; + std::vector textures; typedef std::map MaterialMap; MaterialMap materials_converted; + typedef std::map VideoMap; + VideoMap textures_converted; + typedef std::map > MeshMap; MeshMap meshes_converted; diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 67ca99466..d934c9754 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -180,6 +180,9 @@ const Object* LazyObject::Get(bool dieOnError) else if (!strncmp(obtype,"LayeredTexture",length)) { object.reset(new LayeredTexture(id,element,doc,name)); } + else if (!strncmp(obtype,"Video",length)) { + object.reset(new Video(id,element,doc,name)); + } else if (!strncmp(obtype,"AnimationStack",length)) { object.reset(new AnimationStack(id,element,name,doc)); } diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 6a0c71c8a..a149eb446 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -73,6 +73,8 @@ namespace FBX { class Material; class Geometry; + class Video; + class AnimationCurve; class AnimationCurveNode; class AnimationLayer; @@ -571,6 +573,10 @@ public: return crop; } + const Video* Media() const { + return media; + } + private: aiVector2D uvTrans; @@ -583,6 +589,8 @@ private: boost::shared_ptr props; unsigned int crop[4]; + + const Video* media; }; /** DOM class for layered FBX textures */ @@ -654,6 +662,60 @@ typedef std::fbx_unordered_map TextureMap; typedef std::fbx_unordered_map LayeredTextureMap; +/** DOM class for generic FBX videos */ +class Video : public Object +{ +public: + + Video(uint64_t id, const Element& element, const Document& doc, const std::string& name); + ~Video(); + +public: + + const std::string& Type() const { + return type; + } + + const std::string& FileName() const { + return fileName; + } + + const std::string& RelativeFilename() const { + return relativeFileName; + } + + const PropertyTable& Props() const { + ai_assert(props.get()); + return *props.get(); + } + + const uint8_t* Content() const { + ai_assert(content); + return content; + } + + const uint32_t ContentLength() const { + return contentLength; + } + + uint8_t* RelinquishContent() { + uint8_t* ptr = content; + content = 0; + contentLength = 0; + return ptr; + } + +private: + + std::string type; + std::string relativeFileName; + std::string fileName; + boost::shared_ptr props; + + uint32_t contentLength; + uint8_t* content; +}; + /** DOM class for generic FBX materials */ class Material : public Object { diff --git a/code/FBXImportSettings.h b/code/FBXImportSettings.h index 13c266ada..484241c52 100644 --- a/code/FBXImportSettings.h +++ b/code/FBXImportSettings.h @@ -55,6 +55,7 @@ struct ImportSettings , readAllLayers(true) , readAllMaterials(false) , readMaterials(true) + , readTextures(true) , readCameras(true) , readLights(true) , readAnimations(true) @@ -92,6 +93,9 @@ struct ImportSettings * material. The default value is true.*/ bool readMaterials; + /** import embedded textures? Default value is true.*/ + bool readTextures; + /** import cameras? Default value is true.*/ bool readCameras; diff --git a/code/FBXImporter.cpp b/code/FBXImporter.cpp index d7e4926aa..9bfc4fd2a 100644 --- a/code/FBXImporter.cpp +++ b/code/FBXImporter.cpp @@ -126,6 +126,7 @@ void FBXImporter::SetupProperties(const Importer* pImp) settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true); settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false); settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true); + settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true); settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true); settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true); settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true); diff --git a/code/FBXMaterial.cpp b/code/FBXMaterial.cpp index 03f292168..ced7247c6 100644 --- a/code/FBXMaterial.cpp +++ b/code/FBXMaterial.cpp @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXImportSettings.h" #include "FBXDocumentUtil.h" #include "FBXProperties.h" +#include "ByteSwapper.h" #include namespace Assimp { @@ -147,6 +148,7 @@ Material::~Material() Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) : Object(id,element,name) , uvScaling(1.0f,1.0f) +, media(0) { const Scope& sc = GetRequiredScope(element); @@ -199,6 +201,23 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const } props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc); + + // resolve video links + if(doc.Settings().readTextures) { + const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID()); + BOOST_FOREACH(const Connection* con, conns) { + const Object* const ob = con->SourceObject(); + if(!ob) { + DOMWarning("failed to read source object for texture link, ignoring",&element); + continue; + } + + const Video* const video = dynamic_cast(ob); + if(video) { + media = video; + } + } + } } @@ -253,6 +272,68 @@ void LayeredTexture::fillTexture(const Document& doc) } } + +// ------------------------------------------------------------------------------------------------ +Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name) +: Object(id,element,name) +, contentLength(0) +, content(0) +{ + const Scope& sc = GetRequiredScope(element); + + const Element* const Type = sc["Type"]; + const Element* const FileName = sc["FileName"]; + const Element* const RelativeFilename = sc["RelativeFilename"]; + const Element* const Content = sc["Content"]; + + if(Type) { + type = ParseTokenAsString(GetRequiredToken(*Type,0)); + } + + if(FileName) { + fileName = ParseTokenAsString(GetRequiredToken(*FileName,0)); + } + + if(RelativeFilename) { + relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0)); + } + + if(Content) { + const Token& token = GetRequiredToken(*Content, 0); + const char* data = token.begin(); + if(!token.IsBinary()) { + DOMWarning("video content is not binary data, ignoring", &element); + } + else if(static_cast(token.end() - data) < 5) { + DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element); + } + else if(*data != 'R') { + DOMWarning("video content is not raw binary data, ignoring", &element); + } + else { + // read number of elements + uint32_t len = 0; + ::memcpy(&len, data + 1, sizeof(len)); + AI_SWAP4(len); + + contentLength = len; + + content = new uint8_t[len]; + ::memcpy(content, data + 5, len); + } + } + + props = GetPropertyTable(doc,"Video.FbxVideo",element,sc); +} + + +Video::~Video() +{ + if(content) { + delete[] content; + } +} + } //!FBX } //!Assimp diff --git a/include/assimp/config.h b/include/assimp/config.h index 4b2546760..1f145bfc0 100644 --- a/include/assimp/config.h +++ b/include/assimp/config.h @@ -561,6 +561,15 @@ enum aiComponent #define AI_CONFIG_IMPORT_FBX_READ_MATERIALS \ "IMPORT_FBX_READ_MATERIALS" +// --------------------------------------------------------------------------- +/** @brief Set whether the fbx importer will read embedded textures. + * + * The default value is true (1) + * Property type: bool + */ +#define AI_CONFIG_IMPORT_FBX_READ_TEXTURES \ + "IMPORT_FBX_READ_TEXTURES" + // --------------------------------------------------------------------------- /** @brief Set whether the fbx importer will read cameras. * From 70540616ce46f95628aa5b8336634a8a694486e8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 23 Nov 2015 21:28:35 +0100 Subject: [PATCH 52/77] issue 693: add missing release call in c-export interface. --- code/AssimpCExport.cpp | 30 +++++++++++++++++++++++++++--- include/assimp/cexport.h | 9 ++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/code/AssimpCExport.cpp b/code/AssimpCExport.cpp index 6578eeb88..6df99d86b 100644 --- a/code/AssimpCExport.cpp +++ b/code/AssimpCExport.cpp @@ -59,13 +59,37 @@ ASSIMP_API size_t aiGetExportFormatCount(void) // ------------------------------------------------------------------------------------------------ -ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex) +ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index) { - // Note: this is valid as the index always pertains to a builtin exporter, + // Note: this is valid as the index always pertains to a built-in exporter, // for which the returned structure is guaranteed to be of static storage duration. - return Exporter().GetExportFormatDescription(pIndex); + const aiExportFormatDesc* orig( Exporter().GetExportFormatDescription( index ) ); + if (NULL == orig) { + return NULL; + } + + aiExportFormatDesc *desc = new aiExportFormatDesc; + desc->description = new char[ strlen( orig->description ) + 1 ]; + ::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) ); + desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ]; + ::strncpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) ); + desc->id = new char[ strlen( orig->id ) + 1 ]; + ::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) ); + + return desc; } +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiReleaseExportFormatDescription( const aiExportFormatDesc *desc ) { + if (NULL == desc) { + return; + } + + delete [] desc->description; + delete [] desc->fileExtension; + delete [] desc->id; + delete desc; +} // ------------------------------------------------------------------------------------------------ ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut) diff --git a/include/assimp/cexport.h b/include/assimp/cexport.h index 4afa3156a..71cb1f8ec 100644 --- a/include/assimp/cexport.h +++ b/include/assimp/cexport.h @@ -86,13 +86,20 @@ ASSIMP_API size_t aiGetExportFormatCount(void); // -------------------------------------------------------------------------------- /** Returns a description of the nth export file format. Use #aiGetExportFormatCount() - * to learn how many export formats are supported. + * to learn how many export formats are supported. The description must be released by + * calling aiReleaseExportFormatDescription afterwards. * @param pIndex Index of the export format to retrieve information for. Valid range is * 0 to #aiGetExportFormatCount() * @return A description of that specific export format. NULL if pIndex is out of range. */ ASSIMP_API const C_STRUCT aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex); +// -------------------------------------------------------------------------------- +/** Release a description of the nth export file format. Must be returned by +* aiGetExportFormatDescription +* @param desc Pointer to the description +*/ +ASSIMP_API void aiReleaseExportFormatDescription( const C_STRUCT aiExportFormatDesc *desc ); // -------------------------------------------------------------------------------- /** Create a modifiable copy of a scene. From c876dce82b3c84551118eea425a4dd9263bcaeab Mon Sep 17 00:00:00 2001 From: Otger Date: Mon, 23 Nov 2015 21:46:55 +0100 Subject: [PATCH 53/77] Fixed crashes for Video with no content --- code/FBXConverter.cpp | 2 +- code/FBXDocument.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 21cb8055d..27d43e753 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1499,7 +1499,7 @@ private: path.Set(tex->RelativeFilename()); const Video* media = tex->Media(); - if(media != 0) { + if(media != 0 && media->ContentLength() > 0) { unsigned int index; VideoMap::const_iterator it = textures_converted.find(media); diff --git a/code/FBXDocument.h b/code/FBXDocument.h index a149eb446..3d8f18801 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -701,7 +701,6 @@ public: uint8_t* RelinquishContent() { uint8_t* ptr = content; content = 0; - contentLength = 0; return ptr; } From da013350f9f9cfa6b89f5fe8f36c669b3f37bb66 Mon Sep 17 00:00:00 2001 From: Yotam Gingold Date: Mon, 23 Nov 2015 23:50:25 -0500 Subject: [PATCH 54/77] aiGetExportFormatDescription() no longer uses free'd memory aiGetExportFormatDescription() now creates an Exporter object at the beginning of the function, so that a call to `GetExportFormatDescription()` doesn't access free'd memory. --- code/AssimpCExport.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/AssimpCExport.cpp b/code/AssimpCExport.cpp index 6df99d86b..2d40abc22 100644 --- a/code/AssimpCExport.cpp +++ b/code/AssimpCExport.cpp @@ -63,7 +63,8 @@ ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index) { // Note: this is valid as the index always pertains to a built-in exporter, // for which the returned structure is guaranteed to be of static storage duration. - const aiExportFormatDesc* orig( Exporter().GetExportFormatDescription( index ) ); + Exporter exporter; + const aiExportFormatDesc* orig( exporter.GetExportFormatDescription( index ) ); if (NULL == orig) { return NULL; } From 3c358a8e34ea412e6dc4301ae2236e696bddecc2 Mon Sep 17 00:00:00 2001 From: Otger Date: Tue, 24 Nov 2015 16:33:31 +0100 Subject: [PATCH 55/77] Updated dumps for FBX files --- include/assimp/texture.h | 4 ++++ test/regression/db.zip | Bin 1475266 -> 1475197 bytes 2 files changed, 4 insertions(+) diff --git a/include/assimp/texture.h b/include/assimp/texture.h index 40faf497e..1ec3bbf31 100644 --- a/include/assimp/texture.h +++ b/include/assimp/texture.h @@ -116,6 +116,10 @@ struct aiTexel * 2. Compressed textures stored in a file format like png or jpg. The raw file * bytes are given so the application must utilize an image decoder (e.g. DevIL) to * get access to the actual color data. + * + * Embedded textures are referenced from materials using strings like "*0", "*1", etc. + * as the texture paths (a single asterisk character followed by the + * zero-based index of the texture in the aiScene::mTextures array). */ struct aiTexture { diff --git a/test/regression/db.zip b/test/regression/db.zip index c94598840c94ccdbb7d8c4f67cd5d7c292c4a489..c7631c2408d88e2acffd7ec67a349531e639ce09 100644 GIT binary patch delta 161482 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

+namespace picojson {
+
+  class value {
+    ...
+
+  public:
+
+    typedef std::vector<value> array;
+    typedef std::map<std::string, value> object;
+
+    value();                               // create a null object
+    explicit value(bool b);                // create a boolean object
+    explicit value(double n);              // create a number object
+    explicit value(const std::string& s);  // create a string object
+    explicit value(const array& a);        // create an array object
+    explicit value(const object& o);       // create an "object"
+
+    bool is<picojson::null>() const;       // check if the object is "null"
+
+    bool is<bool>() const;                 // check if the object is a boolean
+    const bool& get<bool>() const;         // const accessor (usable only if the object is a boolean)
+    bool& get<bool>();                     // non-const accessor (usable only if the object is a boolean)
+
+    bool is<double>() const;               // check if the object is a number
+    const double& get<double>() const;     // const accessor (usable only if the object is a number)
+    double& get<double>();                 // non-const accessor (usable only if the object is a number)
+
+    bool is<std::string>() const;          // check if the object is a string
+    const std::string& get<std::string>() const;
+                                           // const accessor (usable only if the object is a string)
+    std::string& get<std::string>();       // non-const accessor (usable only if the object is a string)
+
+    bool is<array>() const;                // check if the object is an array
+    const array& get<array>() const;       // const accessor (usable only if the object is an array)
+    array& get<array>();                   // non-const accessor (usable only if the object is an array)
+
+    bool is<object>() const;               // check if the object is an "object"
+    const object& get<object>() const;     // const accessor (usable only if the object is an object)
+    object& get<object>();                 // non-const accessor (usable only if the object is an array)
+
+    bool evaluate_as_boolean() const;      // evaluates the object as a boolean
+
+    std::string serialize() const;         // returns the object in JSON representation
+    template void serialize(Iter os) const;
+                                           // serializes the object in JSON representation through an output iterator
+
+    std::string to_str() const;            // returns the object in string (for casual use)
+
+  };
+
+}
+
+ +The code below parses a JSON string and prints the contents of the object. + +
+picojson::value v;
+
+// parse the input
+std::cin >> v;
+std::string err = picojson::get_last_error();
+if (! err.empty()) {
+  std::cerr << err << std::endl;
+  exit(1);
+}
+
+// check if the type of the value is "object"
+if (! v.is<picojson::object>()) {
+  std::cerr << "JSON is not an object" << std::endl;
+  exit(2);
+}
+
+// obtain a const reference to the map, and print the contents
+const picojson::value::object& obj = v.get<picojson::object>();
+for (picojson::value::object::const_iterator i = obj.begin();
+     i != obj.end();
+     ++i) {
+  std::cout << i->first << ': ' << i->second.to_str() << std::endl;
+}
+
+ +Please note that the type check is mandatory; do not forget to check the type of the object by calling is<type>() before accessing the value by calling get<type>(). + +## Reading JSON using the streaming (event-driven) interface + +Please refer to the implementation of picojson::default_parse_context and picojson::null_parse_context. There is also an example (examples/streaming.cc) . + +## Serializing to JSON + +Instances of the picojson::value class can be serialized in three ways, to ostream, to std::string, or to an output iterator. + +
+picojson::value v;
+...
+std::cout << v;
+
+ +
+picojson::value v;
+...
+std::string json = v.serialize();
+
+ +
+picojson::value v;
+...
+v.serialize(std::ostream_iterator(std::cout));
+
+ +## Experimental support for int64_t + +Experimental suport for int64_t becomes available if the code is compiled with preprocessor macro `PICOJSON_USE_INT64`. + +Turning on the feature will cause following changes to picojson: +- new constructor `picojson::value(int64_t)` is defined +- `is()` and `get()` become available +- numerics in JSON within the bounds of int64_t and not using `.` nor `e`/`E` are considered as int64 type + - the values are also avaliable as `double`s as well (i.e. all values which are `.is() == true` are also `.is() == true`) +- int64 values are converted to double once `get()` is called + +Enabling the feature should not cause compatibility problem with code that do not use the feature. + +## Further reading + +Examples can be found in the examples directory, and on the [Wiki](https://github.com/kazuho/picojson/wiki). Please add your favorite examples to the Wiki. diff --git a/contrib/picojson/examples/github-issues.cc b/contrib/picojson/examples/github-issues.cc new file mode 100644 index 000000000..3e05afdc7 --- /dev/null +++ b/contrib/picojson/examples/github-issues.cc @@ -0,0 +1,110 @@ +/* + * Copyright 2009-2010 Cybozu Labs, Inc. + * Copyright 2011-2014 Kazuho Oku + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include "../picojson.h" + +typedef struct { + char* data; // response data from server + size_t size; // response size of data +} MEMFILE; + +MEMFILE* +memfopen() { + MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE)); + mf->data = NULL; + mf->size = 0; + return mf; +} + +void +memfclose(MEMFILE* mf) { + if (mf->data) free(mf->data); + free(mf); +} + +size_t +memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) { + MEMFILE* mf = (MEMFILE*) stream; + int block = size * nmemb; + if (!mf->data) + mf->data = (char*) malloc(block); + else + mf->data = (char*) realloc(mf->data, mf->size + block); + if (mf->data) { + memcpy(mf->data + mf->size, ptr, block); + mf->size += block; + } + return block; +} + +char* +memfstrdup(MEMFILE* mf) { + char* buf = (char*)malloc(mf->size + 1); + memcpy(buf, mf->data, mf->size); + buf[mf->size] = 0; + return buf; +} + +using namespace std; +using namespace picojson; + +int +main(int argc, char* argv[]) { + char error[256]; + + MEMFILE* mf = memfopen(); + CURL* curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_URL, "https://api.github.com/repos/kazuho/picojson/issues"); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl"); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf); + if (curl_easy_perform(curl) != CURLE_OK) { + cerr << error << endl; + } else { + value v; + string err; + parse(v, mf->data, mf->data + mf->size, &err); + if (err.empty()) { + array arr = v.get(); + array::iterator it; + for (it = arr.begin(); it != arr.end(); it++) { + object obj = it->get(); + cout << "#" << obj["number"].to_str() << ": " << obj["title"].to_str() << endl; + cout << " " << obj["html_url"].to_str() << endl << endl; + } + } else { + cerr << err << endl; + } + } + curl_easy_cleanup(curl); + memfclose(mf); + + return 0; +} diff --git a/contrib/picojson/examples/iostream.cc b/contrib/picojson/examples/iostream.cc new file mode 100644 index 000000000..30cc93fd4 --- /dev/null +++ b/contrib/picojson/examples/iostream.cc @@ -0,0 +1,70 @@ +/* + * Copyright 2009-2010 Cybozu Labs, Inc. + * Copyright 2011-2014 Kazuho Oku + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "../picojson.h" + +int main(void) +{ + picojson::value v; + + // read json value from stream + std::cin >> v; + if (std::cin.fail()) { + std::cerr << picojson::get_last_error() << std::endl; + return 1; + } + + // dump json object + std::cout << "---- dump input ----" << std::endl; + std::cout << v << std::endl; + + // accessors + std::cout << "---- analyzing input ----" << std::endl; + if (v.is()) { + std::cout << "input is null" << std::endl; + } else if (v.is()) { + std::cout << "input is " << (v.get() ? "true" : "false") << std::endl; + } else if (v.is()) { + std::cout << "input is " << v.get() << std::endl; + } else if (v.is()) { + std::cout << "input is " << v.get() << std::endl; + } else if (v.is()) { + std::cout << "input is an array" << std::endl; + const picojson::array& a = v.get(); + for (picojson::array::const_iterator i = a.begin(); i != a.end(); ++i) { + std::cout << " " << *i << std::endl; + } + } else if (v.is()) { + std::cout << "input is an object" << std::endl; + const picojson::object& o = v.get(); + for (picojson::object::const_iterator i = o.begin(); i != o.end(); ++i) { + std::cout << i->first << " " << i->second << std::endl; + } + } + + return 0; +} diff --git a/contrib/picojson/examples/streaming.cc b/contrib/picojson/examples/streaming.cc new file mode 100644 index 000000000..8b1225f31 --- /dev/null +++ b/contrib/picojson/examples/streaming.cc @@ -0,0 +1,76 @@ +/* + * Copyright 2009-2010 Cybozu Labs, Inc. + * Copyright 2011-2014 Kazuho Oku + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include "../picojson.h" + +// this example reads a array of hashes (each item representing a 2D point), +// and prints the x and y values to stdout + +namespace { + + class root_context : public picojson::deny_parse_context { + public: + bool parse_array_start() { + return true; // only allow array as root + } + template bool parse_array_item(picojson::input& in, size_t) { + picojson::value item; + // parse the array item + picojson::default_parse_context ctx(&item); + if (! picojson::_parse(ctx, in)) { + return false; + } + // assert that the array item is a hash + if (! item.is()) { + return false; + } + // print x and y + std::cout << item.get("x") << ',' << item.get("y").to_str() + << std::endl; + return true; + } + }; + +} + +int main(void) +{ + root_context ctx; + std::string err; + + picojson::_parse(ctx, std::istream_iterator(std::cin), + std::istream_iterator(), &err); + + if (! err.empty()) { + std::cerr << err << std::endl; + return 1; + } + + return 0; +} diff --git a/contrib/picojson/picojson.h b/contrib/picojson/picojson.h new file mode 100644 index 000000000..045dc537b --- /dev/null +++ b/contrib/picojson/picojson.h @@ -0,0 +1,1039 @@ +/* + * Copyright 2009-2010 Cybozu Labs, Inc. + * Copyright 2011-2014 Kazuho Oku + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef picojson_h +#define picojson_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// for isnan/isinf +#if __cplusplus>=201103L +# include +#else +extern "C" { +# ifdef _MSC_VER +# include +# elif defined(__INTEL_COMPILER) +# include +# else +# include +# endif +} +#endif + +#ifndef PICOJSON_USE_RVALUE_REFERENCE +# if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || (defined(_MSC_VER) && _MSC_VER >= 1600) +# define PICOJSON_USE_RVALUE_REFERENCE 1 +# else +# define PICOJSON_USE_RVALUE_REFERENCE 0 +# endif +#endif//PICOJSON_USE_RVALUE_REFERENCE + + +// experimental support for int64_t (see README.mkdn for detail) +#ifdef PICOJSON_USE_INT64 +# define __STDC_FORMAT_MACROS +# include +# include +#endif + +// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0 +#ifndef PICOJSON_USE_LOCALE +# define PICOJSON_USE_LOCALE 1 +#endif +#if PICOJSON_USE_LOCALE +extern "C" { +# include +} +#endif + +#ifndef PICOJSON_ASSERT +# define PICOJSON_ASSERT(e) do { if (! (e)) throw std::runtime_error(#e); } while (0) +#endif + +#ifdef _MSC_VER + #define SNPRINTF _snprintf_s + #pragma warning(push) + #pragma warning(disable : 4244) // conversion from int to char + #pragma warning(disable : 4127) // conditional expression is constant + #pragma warning(disable : 4702) // unreachable code +#else + #define SNPRINTF snprintf +#endif + +namespace picojson { + + enum { + null_type, + boolean_type, + number_type, + string_type, + array_type, + object_type +#ifdef PICOJSON_USE_INT64 + , int64_type +#endif + }; + + enum { + INDENT_WIDTH = 2 + }; + + struct null {}; + + class value { + public: + typedef std::vector array; + typedef std::map object; + union _storage { + bool boolean_; + double number_; +#ifdef PICOJSON_USE_INT64 + int64_t int64_; +#endif + std::string* string_; + array* array_; + object* object_; + }; + protected: + int type_; + _storage u_; + public: + value(); + value(int type, bool); + explicit value(bool b); +#ifdef PICOJSON_USE_INT64 + explicit value(int64_t i); +#endif + explicit value(double n); + explicit value(const std::string& s); + explicit value(const array& a); + explicit value(const object& o); + explicit value(const char* s); + value(const char* s, size_t len); + ~value(); + value(const value& x); + value& operator=(const value& x); +#if PICOJSON_USE_RVALUE_REFERENCE + value(value&& x)throw(); + value& operator=(value&& x)throw(); +#endif + void swap(value& x)throw(); + template bool is() const; + template const T& get() const; + template T& get(); + bool evaluate_as_boolean() const; + const value& get(size_t idx) const; + const value& get(const std::string& key) const; + value& get(size_t idx); + value& get(const std::string& key); + + bool contains(size_t idx) const; + bool contains(const std::string& key) const; + std::string to_str() const; + template void serialize(Iter os, bool prettify = false) const; + std::string serialize(bool prettify = false) const; + private: + template value(const T*); // intentionally defined to block implicit conversion of pointer to bool + template static void _indent(Iter os, int indent); + template void _serialize(Iter os, int indent) const; + std::string _serialize(int indent) const; + }; + + typedef value::array array; + typedef value::object object; + + inline value::value() : type_(null_type) {} + + inline value::value(int type, bool) : type_(type) { + switch (type) { +#define INIT(p, v) case p##type: u_.p = v; break + INIT(boolean_, false); + INIT(number_, 0.0); +#ifdef PICOJSON_USE_INT64 + INIT(int64_, 0); +#endif + INIT(string_, new std::string()); + INIT(array_, new array()); + INIT(object_, new object()); +#undef INIT + default: break; + } + } + + inline value::value(bool b) : type_(boolean_type) { + u_.boolean_ = b; + } + +#ifdef PICOJSON_USE_INT64 + inline value::value(int64_t i) : type_(int64_type) { + u_.int64_ = i; + } +#endif + + inline value::value(double n) : type_(number_type) { + if ( +#ifdef _MSC_VER + ! _finite(n) +#elif __cplusplus>=201103L || !(defined(isnan) && defined(isinf)) + std::isnan(n) || std::isinf(n) +#else + isnan(n) || isinf(n) +#endif + ) { + throw std::overflow_error(""); + } + u_.number_ = n; + } + + inline value::value(const std::string& s) : type_(string_type) { + u_.string_ = new std::string(s); + } + + inline value::value(const array& a) : type_(array_type) { + u_.array_ = new array(a); + } + + inline value::value(const object& o) : type_(object_type) { + u_.object_ = new object(o); + } + + inline value::value(const char* s) : type_(string_type) { + u_.string_ = new std::string(s); + } + + inline value::value(const char* s, size_t len) : type_(string_type) { + u_.string_ = new std::string(s, len); + } + + inline value::~value() { + switch (type_) { +#define DEINIT(p) case p##type: delete u_.p; break + DEINIT(string_); + DEINIT(array_); + DEINIT(object_); +#undef DEINIT + default: break; + } + } + + inline value::value(const value& x) : type_(x.type_) { + switch (type_) { +#define INIT(p, v) case p##type: u_.p = v; break + INIT(string_, new std::string(*x.u_.string_)); + INIT(array_, new array(*x.u_.array_)); + INIT(object_, new object(*x.u_.object_)); +#undef INIT + default: + u_ = x.u_; + break; + } + } + + inline value& value::operator=(const value& x) { + if (this != &x) { + value t(x); + swap(t); + } + return *this; + } + +#if PICOJSON_USE_RVALUE_REFERENCE + inline value::value(value&& x)throw() : type_(null_type) { + swap(x); + } + inline value& value::operator=(value&& x)throw() { + swap(x); + return *this; + } +#endif + inline void value::swap(value& x)throw() { + std::swap(type_, x.type_); + std::swap(u_, x.u_); + } + +#define IS(ctype, jtype) \ + template <> inline bool value::is() const { \ + return type_ == jtype##_type; \ + } + IS(null, null) + IS(bool, boolean) +#ifdef PICOJSON_USE_INT64 + IS(int64_t, int64) +#endif + IS(std::string, string) + IS(array, array) + IS(object, object) +#undef IS + template <> inline bool value::is() const { + return type_ == number_type +#ifdef PICOJSON_USE_INT64 + || type_ == int64_type +#endif + ; + } + +#define GET(ctype, var) \ + template <> inline const ctype& value::get() const { \ + PICOJSON_ASSERT("type mismatch! call is() before get()" \ + && is()); \ + return var; \ + } \ + template <> inline ctype& value::get() { \ + PICOJSON_ASSERT("type mismatch! call is() before get()" \ + && is()); \ + return var; \ + } + GET(bool, u_.boolean_) + GET(std::string, *u_.string_) + GET(array, *u_.array_) + GET(object, *u_.object_) +#ifdef PICOJSON_USE_INT64 + GET(double, (type_ == int64_type && (const_cast(this)->type_ = number_type, const_cast(this)->u_.number_ = u_.int64_), u_.number_)) + GET(int64_t, u_.int64_) +#else + GET(double, u_.number_) +#endif +#undef GET + + inline bool value::evaluate_as_boolean() const { + switch (type_) { + case null_type: + return false; + case boolean_type: + return u_.boolean_; + case number_type: + return u_.number_ != 0; +#ifdef PICOJSON_USE_INT64 + case int64_type: + return u_.int64_ != 0; +#endif + case string_type: + return ! u_.string_->empty(); + default: + return true; + } + } + + inline const value& value::get(size_t idx) const { + static value s_null; + PICOJSON_ASSERT(is()); + return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; + } + + inline value& value::get(size_t idx) { + static value s_null; + PICOJSON_ASSERT(is()); + return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; + } + + inline const value& value::get(const std::string& key) const { + static value s_null; + PICOJSON_ASSERT(is()); + object::const_iterator i = u_.object_->find(key); + return i != u_.object_->end() ? i->second : s_null; + } + + inline value& value::get(const std::string& key) { + static value s_null; + PICOJSON_ASSERT(is()); + object::iterator i = u_.object_->find(key); + return i != u_.object_->end() ? i->second : s_null; + } + + inline bool value::contains(size_t idx) const { + PICOJSON_ASSERT(is()); + return idx < u_.array_->size(); + } + + inline bool value::contains(const std::string& key) const { + PICOJSON_ASSERT(is()); + object::const_iterator i = u_.object_->find(key); + return i != u_.object_->end(); + } + + inline std::string value::to_str() const { + switch (type_) { + case null_type: return "null"; + case boolean_type: return u_.boolean_ ? "true" : "false"; +#ifdef PICOJSON_USE_INT64 + case int64_type: { + char buf[sizeof("-9223372036854775808")]; + SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_); + return buf; + } +#endif + case number_type: { + char buf[256]; + double tmp; + SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_); +#if PICOJSON_USE_LOCALE + char *decimal_point = localeconv()->decimal_point; + if (strcmp(decimal_point, ".") != 0) { + size_t decimal_point_len = strlen(decimal_point); + for (char *p = buf; *p != '\0'; ++p) { + if (strncmp(p, decimal_point, decimal_point_len) == 0) { + return std::string(buf, p) + "." + (p + decimal_point_len); + } + } + } +#endif + return buf; + } + case string_type: return *u_.string_; + case array_type: return "array"; + case object_type: return "object"; + default: PICOJSON_ASSERT(0); +#ifdef _MSC_VER + __assume(0); +#endif + } + return std::string(); + } + + template void copy(const std::string& s, Iter oi) { + std::copy(s.begin(), s.end(), oi); + } + + template void serialize_str(const std::string& s, Iter oi) { + *oi++ = '"'; + for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { + switch (*i) { +#define MAP(val, sym) case val: copy(sym, oi); break + MAP('"', "\\\""); + MAP('\\', "\\\\"); + MAP('/', "\\/"); + MAP('\b', "\\b"); + MAP('\f', "\\f"); + MAP('\n', "\\n"); + MAP('\r', "\\r"); + MAP('\t', "\\t"); +#undef MAP + default: + if (static_cast(*i) < 0x20 || *i == 0x7f) { + char buf[7]; + SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff); + copy(buf, buf + 6, oi); + } else { + *oi++ = *i; + } + break; + } + } + *oi++ = '"'; + } + + template void value::serialize(Iter oi, bool prettify) const { + return _serialize(oi, prettify ? 0 : -1); + } + + inline std::string value::serialize(bool prettify) const { + return _serialize(prettify ? 0 : -1); + } + + template void value::_indent(Iter oi, int indent) { + *oi++ = '\n'; + for (int i = 0; i < indent * INDENT_WIDTH; ++i) { + *oi++ = ' '; + } + } + + template void value::_serialize(Iter oi, int indent) const { + switch (type_) { + case string_type: + serialize_str(*u_.string_, oi); + break; + case array_type: { + *oi++ = '['; + if (indent != -1) { + ++indent; + } + for (array::const_iterator i = u_.array_->begin(); + i != u_.array_->end(); + ++i) { + if (i != u_.array_->begin()) { + *oi++ = ','; + } + if (indent != -1) { + _indent(oi, indent); + } + i->_serialize(oi, indent); + } + if (indent != -1) { + --indent; + if (! u_.array_->empty()) { + _indent(oi, indent); + } + } + *oi++ = ']'; + break; + } + case object_type: { + *oi++ = '{'; + if (indent != -1) { + ++indent; + } + for (object::const_iterator i = u_.object_->begin(); + i != u_.object_->end(); + ++i) { + if (i != u_.object_->begin()) { + *oi++ = ','; + } + if (indent != -1) { + _indent(oi, indent); + } + serialize_str(i->first, oi); + *oi++ = ':'; + if (indent != -1) { + *oi++ = ' '; + } + i->second._serialize(oi, indent); + } + if (indent != -1) { + --indent; + if (! u_.object_->empty()) { + _indent(oi, indent); + } + } + *oi++ = '}'; + break; + } + default: + copy(to_str(), oi); + break; + } + if (indent == 0) { + *oi++ = '\n'; + } + } + + inline std::string value::_serialize(int indent) const { + std::string s; + _serialize(std::back_inserter(s), indent); + return s; + } + + template class input { + protected: + Iter cur_, end_; + int last_ch_; + bool ungot_; + int line_; + public: + input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {} + int getc() { + if (ungot_) { + ungot_ = false; + return last_ch_; + } + if (cur_ == end_) { + last_ch_ = -1; + return -1; + } + if (last_ch_ == '\n') { + line_++; + } + last_ch_ = *cur_ & 0xff; + ++cur_; + return last_ch_; + } + void ungetc() { + if (last_ch_ != -1) { + PICOJSON_ASSERT(! ungot_); + ungot_ = true; + } + } + Iter cur() const { return cur_; } + int line() const { return line_; } + void skip_ws() { + while (1) { + int ch = getc(); + if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { + ungetc(); + break; + } + } + } + bool expect(int expect) { + skip_ws(); + if (getc() != expect) { + ungetc(); + return false; + } + return true; + } + bool match(const std::string& pattern) { + for (std::string::const_iterator pi(pattern.begin()); + pi != pattern.end(); + ++pi) { + if (getc() != *pi) { + ungetc(); + return false; + } + } + return true; + } + }; + + template inline int _parse_quadhex(input &in) { + int uni_ch = 0, hex; + for (int i = 0; i < 4; i++) { + if ((hex = in.getc()) == -1) { + return -1; + } + if ('0' <= hex && hex <= '9') { + hex -= '0'; + } else if ('A' <= hex && hex <= 'F') { + hex -= 'A' - 0xa; + } else if ('a' <= hex && hex <= 'f') { + hex -= 'a' - 0xa; + } else { + in.ungetc(); + return -1; + } + uni_ch = uni_ch * 16 + hex; + } + return uni_ch; + } + + template inline bool _parse_codepoint(String& out, input& in) { + int uni_ch; + if ((uni_ch = _parse_quadhex(in)) == -1) { + return false; + } + if (0xd800 <= uni_ch && uni_ch <= 0xdfff) { + if (0xdc00 <= uni_ch) { + // a second 16-bit of a surrogate pair appeared + return false; + } + // first 16-bit of surrogate pair, get the next one + if (in.getc() != '\\' || in.getc() != 'u') { + in.ungetc(); + return false; + } + int second = _parse_quadhex(in); + if (! (0xdc00 <= second && second <= 0xdfff)) { + return false; + } + uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff); + uni_ch += 0x10000; + } + if (uni_ch < 0x80) { + out.push_back(uni_ch); + } else { + if (uni_ch < 0x800) { + out.push_back(0xc0 | (uni_ch >> 6)); + } else { + if (uni_ch < 0x10000) { + out.push_back(0xe0 | (uni_ch >> 12)); + } else { + out.push_back(0xf0 | (uni_ch >> 18)); + out.push_back(0x80 | ((uni_ch >> 12) & 0x3f)); + } + out.push_back(0x80 | ((uni_ch >> 6) & 0x3f)); + } + out.push_back(0x80 | (uni_ch & 0x3f)); + } + return true; + } + + template inline bool _parse_string(String& out, input& in) { + while (1) { + int ch = in.getc(); + if (ch < ' ') { + in.ungetc(); + return false; + } else if (ch == '"') { + return true; + } else if (ch == '\\') { + if ((ch = in.getc()) == -1) { + return false; + } + switch (ch) { +#define MAP(sym, val) case sym: out.push_back(val); break + MAP('"', '\"'); + MAP('\\', '\\'); + MAP('/', '/'); + MAP('b', '\b'); + MAP('f', '\f'); + MAP('n', '\n'); + MAP('r', '\r'); + MAP('t', '\t'); +#undef MAP + case 'u': + if (! _parse_codepoint(out, in)) { + return false; + } + break; + default: + return false; + } + } else { + out.push_back(ch); + } + } + return false; + } + + template inline bool _parse_array(Context& ctx, input& in) { + if (! ctx.parse_array_start()) { + return false; + } + size_t idx = 0; + if (in.expect(']')) { + return ctx.parse_array_stop(idx); + } + do { + if (! ctx.parse_array_item(in, idx)) { + return false; + } + idx++; + } while (in.expect(',')); + return in.expect(']') && ctx.parse_array_stop(idx); + } + + template inline bool _parse_object(Context& ctx, input& in) { + if (! ctx.parse_object_start()) { + return false; + } + if (in.expect('}')) { + return true; + } + do { + std::string key; + if (! in.expect('"') + || ! _parse_string(key, in) + || ! in.expect(':')) { + return false; + } + if (! ctx.parse_object_item(in, key)) { + return false; + } + } while (in.expect(',')); + return in.expect('}'); + } + + template inline std::string _parse_number(input& in) { + std::string num_str; + while (1) { + int ch = in.getc(); + if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' + || ch == 'e' || ch == 'E') { + num_str.push_back(ch); + } else if (ch == '.') { +#if PICOJSON_USE_LOCALE + num_str += localeconv()->decimal_point; +#else + num_str.push_back('.'); +#endif + } else { + in.ungetc(); + break; + } + } + return num_str; + } + + template inline bool _parse(Context& ctx, input& in) { + in.skip_ws(); + int ch = in.getc(); + switch (ch) { +#define IS(ch, text, op) case ch: \ + if (in.match(text) && op) { \ + return true; \ + } else { \ + return false; \ + } + IS('n', "ull", ctx.set_null()); + IS('f', "alse", ctx.set_bool(false)); + IS('t', "rue", ctx.set_bool(true)); +#undef IS + case '"': + return ctx.parse_string(in); + case '[': + return _parse_array(ctx, in); + case '{': + return _parse_object(ctx, in); + default: + if (('0' <= ch && ch <= '9') || ch == '-') { + double f; + char *endp; + in.ungetc(); + std::string num_str = _parse_number(in); + if (num_str.empty()) { + return false; + } +#ifdef PICOJSON_USE_INT64 + { + errno = 0; + intmax_t ival = strtoimax(num_str.c_str(), &endp, 10); + if (errno == 0 + && std::numeric_limits::min() <= ival + && ival <= std::numeric_limits::max() + && endp == num_str.c_str() + num_str.size()) { + ctx.set_int64(ival); + return true; + } + } +#endif + f = strtod(num_str.c_str(), &endp); + if (endp == num_str.c_str() + num_str.size()) { + ctx.set_number(f); + return true; + } + return false; + } + break; + } + in.ungetc(); + return false; + } + + class deny_parse_context { + public: + bool set_null() { return false; } + bool set_bool(bool) { return false; } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t) { return false; } +#endif + bool set_number(double) { return false; } + template bool parse_string(input&) { return false; } + bool parse_array_start() { return false; } + template bool parse_array_item(input&, size_t) { + return false; + } + bool parse_array_stop(size_t) { return false; } + bool parse_object_start() { return false; } + template bool parse_object_item(input&, const std::string&) { + return false; + } + }; + + class default_parse_context { + protected: + value* out_; + public: + default_parse_context(value* out) : out_(out) {} + bool set_null() { + *out_ = value(); + return true; + } + bool set_bool(bool b) { + *out_ = value(b); + return true; + } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t i) { + *out_ = value(i); + return true; + } +#endif + bool set_number(double f) { + *out_ = value(f); + return true; + } + template bool parse_string(input& in) { + *out_ = value(string_type, false); + return _parse_string(out_->get(), in); + } + bool parse_array_start() { + *out_ = value(array_type, false); + return true; + } + template bool parse_array_item(input& in, size_t) { + array& a = out_->get(); + a.push_back(value()); + default_parse_context ctx(&a.back()); + return _parse(ctx, in); + } + bool parse_array_stop(size_t) { return true; } + bool parse_object_start() { + *out_ = value(object_type, false); + return true; + } + template bool parse_object_item(input& in, const std::string& key) { + object& o = out_->get(); + default_parse_context ctx(&o[key]); + return _parse(ctx, in); + } + private: + default_parse_context(const default_parse_context&); + default_parse_context& operator=(const default_parse_context&); + }; + + class null_parse_context { + public: + struct dummy_str { + void push_back(int) {} + }; + public: + null_parse_context() {} + bool set_null() { return true; } + bool set_bool(bool) { return true; } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t) { return true; } +#endif + bool set_number(double) { return true; } + template bool parse_string(input& in) { + dummy_str s; + return _parse_string(s, in); + } + bool parse_array_start() { return true; } + template bool parse_array_item(input& in, size_t) { + return _parse(*this, in); + } + bool parse_array_stop(size_t) { return true; } + bool parse_object_start() { return true; } + template bool parse_object_item(input& in, const std::string&) { + return _parse(*this, in); + } + private: + null_parse_context(const null_parse_context&); + null_parse_context& operator=(const null_parse_context&); + }; + + // obsolete, use the version below + template inline std::string parse(value& out, Iter& pos, const Iter& last) { + std::string err; + pos = parse(out, pos, last, &err); + return err; + } + + template inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::string* err) { + input in(first, last); + if (! _parse(ctx, in) && err != NULL) { + char buf[64]; + SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line()); + *err = buf; + while (1) { + int ch = in.getc(); + if (ch == -1 || ch == '\n') { + break; + } else if (ch >= ' ') { + err->push_back(ch); + } + } + } + return in.cur(); + } + + template inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err) { + default_parse_context ctx(&out); + return _parse(ctx, first, last, err); + } + + inline std::string parse(value& out, const std::string& s) { + std::string err; + parse(out, s.begin(), s.end(), &err); + return err; + } + + inline std::string parse(value& out, std::istream& is) { + std::string err; + parse(out, std::istreambuf_iterator(is.rdbuf()), + std::istreambuf_iterator(), &err); + return err; + } + + template struct last_error_t { + static std::string s; + }; + template std::string last_error_t::s; + + inline void set_last_error(const std::string& s) { + last_error_t::s = s; + } + + inline const std::string& get_last_error() { + return last_error_t::s; + } + + inline bool operator==(const value& x, const value& y) { + if (x.is()) + return y.is(); +#define PICOJSON_CMP(type) \ + if (x.is()) \ + return y.is() && x.get() == y.get() + PICOJSON_CMP(bool); + PICOJSON_CMP(double); + PICOJSON_CMP(std::string); + PICOJSON_CMP(array); + PICOJSON_CMP(object); +#undef PICOJSON_CMP + PICOJSON_ASSERT(0); +#ifdef _MSC_VER + __assume(0); +#endif + return false; + } + + inline bool operator!=(const value& x, const value& y) { + return ! (x == y); + } +} + +#if !PICOJSON_USE_RVALUE_REFERENCE +namespace std { + template<> inline void swap(picojson::value& x, picojson::value& y) + { + x.swap(y); + } +} +#endif + +inline std::istream& operator>>(std::istream& is, picojson::value& x) +{ + picojson::set_last_error(std::string()); + std::string err = picojson::parse(x, is); + if (! err.empty()) { + picojson::set_last_error(err); + is.setstate(std::ios::failbit); + } + return is; +} + +inline std::ostream& operator<<(std::ostream& os, const picojson::value& x) +{ + x.serialize(std::ostream_iterator(os)); + return os; +} +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#endif diff --git a/contrib/picojson/picotest/picotest.c b/contrib/picojson/picotest/picotest.c new file mode 100644 index 000000000..d1fe699d5 --- /dev/null +++ b/contrib/picojson/picotest/picotest.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014 DeNA Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include +#include +#include +#include "picotest.h" + +struct test_t { + int num_tests; + int failed; +}; +struct test_t main_tests, *cur_tests = &main_tests; +static int test_level = 0; + +static void indent(void) +{ + int i; + for (i = 0; i != test_level; ++i) + printf(" "); +} + +__attribute__((format (printf, 1, 2))) +void note(const char *fmt, ...) +{ + va_list arg; + + indent(); + printf("# "); + + va_start(arg, fmt); + vprintf(fmt, arg); + va_end(arg); + + printf("\n"); +} + +__attribute__((format (printf, 2, 3))) +void _ok(int cond, const char *fmt, ...) +{ + va_list arg; + + if (! cond) + cur_tests->failed = 1; + indent(); + + printf("%s %d - ", cond ? "ok" : "not ok", ++cur_tests->num_tests); + va_start(arg, fmt); + vprintf(fmt, arg); + va_end(arg); + + printf("\n"); +} + +int done_testing(void) +{ + indent(); + printf("1..%d\n", cur_tests->num_tests); + return cur_tests->failed; +} + +void subtest(const char *name, void (*cb)(void)) +{ + struct test_t test = {}, *parent_tests; + + parent_tests = cur_tests; + cur_tests = &test; + ++test_level; + + note("Subtest: %s", name); + + cb(); + + done_testing(); + + --test_level; + cur_tests = parent_tests; + if (test.failed) + cur_tests->failed = 1; + _ok(! test.failed, "%s", name); +} diff --git a/contrib/picojson/picotest/picotest.h b/contrib/picojson/picotest/picotest.h new file mode 100644 index 000000000..22ab02fb2 --- /dev/null +++ b/contrib/picojson/picotest/picotest.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 DeNA Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#ifndef picotest_h +#define picotest_h + +#ifdef __cplusplus +extern "C" { +#endif + +void note(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +void _ok(int cond, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +#define ok(cond) _ok(cond, "%s %d", __FILE__, __LINE__) +int done_testing(void); +void subtest(const char *name, void (*cb)(void)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/picojson/test.cc b/contrib/picojson/test.cc new file mode 100644 index 000000000..73260ca94 --- /dev/null +++ b/contrib/picojson/test.cc @@ -0,0 +1,325 @@ +/* + * Copyright 2009-2010 Cybozu Labs, Inc. + * Copyright 2011-2014 Kazuho Oku, Yasuhiro Matsumoto, Shigeo Mitsunari + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "picojson.h" +#include "picotest/picotest.h" + +#ifdef _MSC_VER + #pragma warning(disable : 4127) // conditional expression is constant +#endif + +using namespace std; + +#define is(x, y, name) _ok((x) == (y), name) + +#include +#include +#include +#include + +int main(void) +{ +#if PICOJSON_USE_LOCALE + setlocale(LC_ALL, ""); +#endif + + // constructors +#define TEST(expr, expected) \ + is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr) + + TEST( (true), "true"); + TEST( (false), "false"); + TEST( (42.0), "42"); + TEST( (string("hello")), "\"hello\""); + TEST( ("hello"), "\"hello\""); + TEST( ("hello", 4), "\"hell\""); + + { + double a = 1; + for (int i = 0; i < 1024; i++) { + picojson::value vi(a); + std::stringstream ss; + ss << vi; + picojson::value vo; + ss >> vo; + double b = vo.get(); + if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) { + printf("ng i=%d a=%.18e b=%.18e\n", i, a, b); + } + a *= 2; + } + } + +#undef TEST + +#define TEST(in, type, cmp, serialize_test) { \ + picojson::value v; \ + const char* s = in; \ + string err = picojson::parse(v, s, s + strlen(s)); \ + _ok(err.empty(), in " no error"); \ + _ok(v.is(), in " check type"); \ + is(v.get(), static_cast(cmp), in " correct output"); \ + is(*s, '\0', in " read to eof"); \ + if (serialize_test) { \ + is(v.serialize(), string(in), in " serialize"); \ + } \ + } + TEST("false", bool, false, true); + TEST("true", bool, true, true); + TEST("90.5", double, 90.5, false); + TEST("1.7976931348623157e+308", double, DBL_MAX, false); + TEST("\"hello\"", string, string("hello"), true); + TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"), + true); + TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string, + string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false); + TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false); +#ifdef PICOJSON_USE_INT64 + TEST("0", int64_t, 0, true); + TEST("-9223372036854775808", int64_t, std::numeric_limits::min(), true); + TEST("9223372036854775807", int64_t, std::numeric_limits::max(), true); +#endif +#undef TEST + +#define TEST(type, expr) { \ + picojson::value v; \ + const char *s = expr; \ + string err = picojson::parse(v, s, s + strlen(s)); \ + _ok(err.empty(), "empty " #type " no error"); \ + _ok(v.is(), "empty " #type " check type"); \ + _ok(v.get().empty(), "check " #type " array size"); \ + } + TEST(array, "[]"); + TEST(object, "{}"); +#undef TEST + + { + picojson::value v; + const char *s = "[1,true,\"hello\"]"; + string err = picojson::parse(v, s, s + strlen(s)); + _ok(err.empty(), "array no error"); + _ok(v.is(), "array check type"); + is(v.get().size(), size_t(3), "check array size"); + _ok(v.contains(0), "check contains array[0]"); + _ok(v.get(0).is(), "check array[0] type"); + is(v.get(0).get(), 1.0, "check array[0] value"); + _ok(v.contains(1), "check contains array[1]"); + _ok(v.get(1).is(), "check array[1] type"); + _ok(v.get(1).get(), "check array[1] value"); + _ok(v.contains(2), "check contains array[2]"); + _ok(v.get(2).is(), "check array[2] type"); + is(v.get(2).get(), string("hello"), "check array[2] value"); + _ok(!v.contains(3), "check not contains array[3]"); + } + + { + picojson::value v; + const char *s = "{ \"a\": true }"; + string err = picojson::parse(v, s, s + strlen(s)); + _ok(err.empty(), "object no error"); + _ok(v.is(), "object check type"); + is(v.get().size(), size_t(1), "check object size"); + _ok(v.contains("a"), "check contains property"); + _ok(v.get("a").is(), "check bool property exists"); + is(v.get("a").get(), true, "check bool property value"); + is(v.serialize(), string("{\"a\":true}"), "serialize object"); + _ok(!v.contains("z"), "check not contains property"); + } + +#define TEST(json, msg) do { \ + picojson::value v; \ + const char *s = json; \ + string err = picojson::parse(v, s, s + strlen(s)); \ + is(err, string("syntax error at line " msg), msg); \ + } while (0) + TEST("falsoa", "1 near: oa"); + TEST("{]", "1 near: ]"); + TEST("\n\bbell", "2 near: bell"); + TEST("\"abc\nd\"", "1 near: "); +#undef TEST + + { + picojson::value v1, v2; + const char *s; + string err; + s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; + err = picojson::parse(v1, s, s + strlen(s)); + s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }"; + err = picojson::parse(v2, s, s + strlen(s)); + _ok((v1 == v2), "check == operator in deep comparison"); + } + + { + picojson::value v1, v2; + const char *s; + string err; + s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; + err = picojson::parse(v1, s, s + strlen(s)); + s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }"; + err = picojson::parse(v2, s, s + strlen(s)); + _ok((v1 != v2), "check != operator for array in deep comparison"); + } + + { + picojson::value v1, v2; + const char *s; + string err; + s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; + err = picojson::parse(v1, s, s + strlen(s)); + s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }"; + err = picojson::parse(v2, s, s + strlen(s)); + _ok((v1 != v2), "check != operator for object in deep comparison"); + } + + { + picojson::value v1, v2; + const char *s; + string err; + s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; + err = picojson::parse(v1, s, s + strlen(s)); + picojson::object& o = v1.get(); + o.erase("b"); + picojson::array& a = o["a"].get(); + picojson::array::iterator i; + i = std::remove(a.begin(), a.end(), picojson::value(std::string("three"))); + a.erase(i, a.end()); + s = "{ \"a\": [1,2], \"d\": 2 }"; + err = picojson::parse(v2, s, s + strlen(s)); + _ok((v1 == v2), "check erase()"); + } + + _ok(picojson::value(3.0).serialize() == "3", + "integral number should be serialized as a integer"); + + { + const char* s = "{ \"a\": [1,2], \"d\": 2 }"; + picojson::null_parse_context ctx; + string err; + picojson::_parse(ctx, s, s + strlen(s), &err); + _ok(err.empty(), "null_parse_context"); + } + + { + picojson::value v1, v2; + v1 = picojson::value(true); + swap(v1, v2); + _ok(v1.is(), "swap (null)"); + _ok(v2.get() == true, "swap (bool)"); + + v1 = picojson::value("a"); + v2 = picojson::value(1.0); + swap(v1, v2); + _ok(v1.get() == 1.0, "swap (dobule)"); + _ok(v2.get() == "a", "swap (string)"); + + v1 = picojson::value(picojson::object()); + v2 = picojson::value(picojson::array()); + swap(v1, v2); + _ok(v1.is(), "swap (array)"); + _ok(v2.is(), "swap (object)"); + } + + { + picojson::value v; + const char *s = "{ \"a\": 1, \"b\": [ 2, { \"b1\": \"abc\" } ], \"c\": {}, \"d\": [] }"; + string err; + err = picojson::parse(v, s, s + strlen(s)); + _ok(err.empty(), "parse test data for prettifying output"); + _ok(v.serialize() == "{\"a\":1,\"b\":[2,{\"b1\":\"abc\"}],\"c\":{},\"d\":[]}", "non-prettifying output"); + _ok(v.serialize(true) == "{\n \"a\": 1,\n \"b\": [\n 2,\n {\n \"b1\": \"abc\"\n }\n ],\n \"c\": {},\n \"d\": []\n}\n", "prettifying output"); + } + + try { + picojson::value v(std::numeric_limits::quiet_NaN()); + _ok(false, "should not accept NaN"); + } catch (std::overflow_error e) { + _ok(true, "should not accept NaN"); + } + + try { + picojson::value v(std::numeric_limits::infinity()); + _ok(false, "should not accept infinity"); + } catch (std::overflow_error e) { + _ok(true, "should not accept infinity"); + } + + try { + picojson::value v(123.); + _ok(! v.is(), "is() should return false"); + v.get(); + _ok(false, "get() should raise an error"); + } catch (std::runtime_error e) { + _ok(true, "get() should raise an error"); + } + +#ifdef PICOJSON_USE_INT64 + { + picojson::value v1((int64_t)123); + _ok(v1.is(), "is int64_t"); + _ok(v1.is(), "is double as well"); + _ok(v1.serialize() == "123", "serialize the value"); + _ok(v1.get() == 123, "value is correct as int64_t"); + _ok(v1.get(), "value is correct as double"); + + _ok(! v1.is(), "is no more int64_type once get() is called"); + _ok(v1.is(), "and is still a double"); + + const char *s = "-9223372036854775809"; + _ok(picojson::parse(v1, s, s + strlen(s)).empty(), "parse underflowing int64_t"); + _ok(! v1.is(), "underflowing int is not int64_t"); + _ok(v1.is(), "underflowing int is double"); + _ok(v1.get() + 9.22337203685478e+18 < 65536, "double value is somewhat correct"); + } +#endif + + { + picojson::value v; + std::string err = picojson::parse(v, "[ 1, \"abc\" ]"); + _ok(err.empty(), "simple API no error"); + _ok(v.is(), "simple API return type is array"); + is(v.get().size(), 2, "simple API array size"); + _ok(v.get()[0].is(), "simple API type #0"); + is(v.get()[0].get(), 1, "simple API value #0"); + _ok(v.get()[1].is(), "simple API type #1"); + is(v.get()[1].get(), "abc", "simple API value #1"); + } + + { + picojson::value v1((double) 0); + _ok(! v1.evaluate_as_boolean(), "((double) 0) is false"); + picojson::value v2((double) 1); + _ok(v2.evaluate_as_boolean(), "((double) 1) is true"); +#ifdef PICOJSON_USE_INT64 + picojson::value v3((int64_t) 0); + _ok(! v3.evaluate_as_boolean(), "((int64_t) 0) is false"); + picojson::value v4((int64_t) 1); + _ok(v4.evaluate_as_boolean(), "((int64_t) 1) is true"); +#endif + } + + return done_testing(); +} diff --git a/test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.bin b/test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.bin new file mode 100644 index 0000000000000000000000000000000000000000..e718eec4d23991a52feb7464b15af0128f9dd41f GIT binary patch literal 113052 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

9@lTW`{w#fcRyeC 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�(1mj5 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 literal 0 HcmV?d00001 diff --git a/test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.gltf b/test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.gltf new file mode 100644 index 000000000..0d66c6fe3 --- /dev/null +++ b/test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.gltf @@ -0,0 +1,705 @@ +{ + "accessors": { + "accessor_100": { + "bufferView": "bufferView_105", + "byteOffset": 7032, + "byteStride": 12, + "componentType": 5126, + "count": 586, + "max": [ + 0.999039, + 0.999038, + 1 + ], + "min": [ + -0.999038, + -0.999038, + -1 + ], + "type": "VEC3" + }, + "accessor_102": { + "bufferView": "bufferView_105", + "byteOffset": 14064, + "byteStride": 8, + "componentType": 5126, + "count": 586, + "max": [ + 0.993657, + 0.989576 + ], + "min": [ + 0.605093, + 0.00905001 + ], + "type": "VEC2" + }, + "accessor_63": { + "bufferView": "bufferView_104", + "byteOffset": 4608, + "byteStride": 0, + "componentType": 5123, + "count": 5232, + "type": "SCALAR" + }, + "accessor_66": { + "bufferView": "bufferView_104", + "byteOffset": 15072, + "byteStride": 0, + "componentType": 5123, + "count": 168, + "type": "SCALAR" + }, + "accessor_69": { + "bufferView": "bufferView_104", + "byteOffset": 15408, + "byteStride": 0, + "componentType": 5123, + "count": 864, + "type": "SCALAR" + }, + "accessor_71": { + "bufferView": "bufferView_105", + "byteOffset": 18752, + "byteStride": 12, + "componentType": 5126, + "count": 2392, + "max": [ + 2.438, + 2.58437, + 1.396 + ], + "min": [ + -2.43091, + 0.2668, + -1.396 + ], + "type": "VEC3" + }, + "accessor_73": { + "bufferView": "bufferView_105", + "byteOffset": 47456, + "byteStride": 12, + "componentType": 5126, + "count": 2392, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + "accessor_75": { + "bufferView": "bufferView_105", + "byteOffset": 76160, + "byteStride": 8, + "componentType": 5126, + "count": 2392, + "max": [ + 0.896458, + 0.997245 + ], + "min": [ + 0.00295639, + 0.015672 + ], + "type": "VEC2" + }, + "accessor_96": { + "bufferView": "bufferView_104", + "byteOffset": 0, + "byteStride": 0, + "componentType": 5123, + "count": 2304, + "type": "SCALAR" + }, + "accessor_98": { + "bufferView": "bufferView_105", + "byteOffset": 0, + "byteStride": 12, + "componentType": 5126, + "count": 586, + "max": [ + 0.4278, + 0.4278, + 1.058 + ], + "min": [ + -0.4278, + -0.4278, + -1.058 + ], + "type": "VEC3" + }, + "animAccessor_0": { + "bufferView": "bufferView_103", + "byteOffset": 0, + "componentType": 5126, + "count": 31, + "type": "SCALAR" + }, + "animAccessor_1": { + "bufferView": "bufferView_103", + "byteOffset": 124, + "componentType": 5126, + "count": 31, + "type": "VEC4" + } + }, + "animations": { + "animation_0": { + "channels": [ + { + "sampler": "animation_0_rotation_sampler", + "target": { + "id": "Geometry-mesh001Node", + "path": "rotation" + } + } + ], + "parameters": { + "TIME": "animAccessor_0", + "rotation": "animAccessor_1" + }, + "samplers": { + "animation_0_rotation_sampler": { + "input": "TIME", + "interpolation": "LINEAR", + "output": "rotation" + } + } + }, + "animation_1": { + "channels": [ + { + "sampler": "animation_1_rotation_sampler", + "target": { + "id": "meshInst962Node", + "path": "rotation" + } + } + ], + "parameters": { + "TIME": "animAccessor_0", + "rotation": "animAccessor_1" + }, + "samplers": { + "animation_1_rotation_sampler": { + "input": "TIME", + "interpolation": "LINEAR", + "output": "rotation" + } + } + } + }, + "asset": { + "generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b", + "premultipliedAlpha": true, + "profile": { + "api": "WebGL", + "version": "1.0.2" + }, + "version": 1 + }, + "bufferViews": { + "bufferView_103": { + "buffer": "CesiumMilkTruck", + "byteLength": 620, + "byteOffset": 0 + }, + "bufferView_104": { + "buffer": "CesiumMilkTruck", + "byteLength": 17136, + "byteOffset": 620, + "target": 34963 + }, + "bufferView_105": { + "buffer": "CesiumMilkTruck", + "byteLength": 95296, + "byteOffset": 17756, + "target": 34962 + } + }, + "buffers": { + "CesiumMilkTruck": { + "byteLength": 113052, + "type": "arraybuffer", + "uri": "CesiumMilkTruck.bin" + } + }, + "images": { + "Image0001": { + "name": "Image0001", + "uri": "CesiumMilkTruck.png" + } + }, + "materials": { + "Effect-glass": { + "name": "glass", + "technique": "technique0", + "values": { + "diffuse": [ + 0, + 0.0405063, + 0.0212407, + 1 + ], + "shininess": 256, + "specular": [ + 0.65, + 0.65, + 0.65, + 1 + ] + } + }, + "Effect-truck": { + "name": "truck", + "technique": "technique1", + "values": { + "diffuse": "texture_Image0001", + "shininess": 256, + "specular": [ + 0.04, + 0.04, + 0.04, + 1 + ] + } + }, + "Effect-wheels": { + "name": "wheels", + "technique": "technique1", + "values": { + "diffuse": "texture_Image0001", + "shininess": 256, + "specular": [ + 0.04, + 0.04, + 0.04, + 1 + ] + } + }, + "Effect-window_trim": { + "name": "window_trim", + "technique": "technique0", + "values": { + "diffuse": [ + 0.064, + 0.064, + 0.064, + 1 + ], + "shininess": 256, + "specular": [ + 0.04, + 0.04, + 0.04, + 1 + ] + } + } + }, + "meshes": { + "Geometry-mesh001": { + "name": "Wheels", + "primitives": [ + { + "attributes": { + "NORMAL": "accessor_100", + "POSITION": "accessor_98", + "TEXCOORD_0": "accessor_102" + }, + "indices": "accessor_96", + "material": "Effect-wheels", + "mode": 4 + } + ] + }, + "Geometry-mesh002": { + "name": "Cesium_Milk_Truck", + "primitives": [ + { + "attributes": { + "NORMAL": "accessor_73", + "POSITION": "accessor_71", + "TEXCOORD_0": "accessor_75" + }, + "indices": "accessor_63", + "material": "Effect-truck", + "mode": 4 + }, + { + "attributes": { + "NORMAL": "accessor_73", + "POSITION": "accessor_71", + "TEXCOORD_0": "accessor_75" + }, + "indices": "accessor_66", + "material": "Effect-glass", + "mode": 4 + }, + { + "attributes": { + "NORMAL": "accessor_73", + "POSITION": "accessor_71", + "TEXCOORD_0": "accessor_75" + }, + "indices": "accessor_69", + "material": "Effect-window_trim", + "mode": 4 + } + ] + } + }, + "nodes": { + "Geometry-mesh001Node": { + "children": [], + "meshes": [ + "Geometry-mesh001" + ], + "name": "Wheels", + "rotation": [ + 0, + 0, + -0.0884856, + 0.996077 + ], + "scale": [ + 1, + 1, + 1 + ], + "translation": [ + 1.43267, + 0.427722, + -2.98023e-008 + ] + }, + "Geometry-mesh002Node": { + "children": [ + "Geometry-mesh001Node", + "meshInst962Node" + ], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "meshes": [ + "Geometry-mesh002" + ], + "name": "Cesium_Milk_Truck" + }, + "groupLocator006Node": { + "children": [ + "txtrLocator003Node", + "txtrLocator013Node" + ], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "name": "Texture_Group" + }, + "meshInst962Node": { + "children": [], + "meshes": [ + "Geometry-mesh001" + ], + "name": "Wheels__2_", + "rotation": [ + 0, + 0, + -0.0884856, + 0.996077 + ], + "scale": [ + 1, + 1, + 1 + ], + "translation": [ + -1.35233, + 0.427722, + -2.98023e-008 + ] + }, + "polyRender006": { + "children": [], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "name": "Render" + }, + "txtrLocator003Node": { + "children": [], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "name": "Cesium_Milk_Truck__2___Image___Texture_" + }, + "txtrLocator013Node": { + "children": [], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "name": "Cesium_Milk_Truck__2___Image___2___Texture_" + } + }, + "programs": { + "program_0": { + "attributes": [ + "a_normal", + "a_position" + ], + "fragmentShader": "CesiumMilkTruck0FS", + "vertexShader": "CesiumMilkTruck0VS" + }, + "program_1": { + "attributes": [ + "a_normal", + "a_position", + "a_texcoord0" + ], + "fragmentShader": "CesiumMilkTruck1FS", + "vertexShader": "CesiumMilkTruck1VS" + } + }, + "samplers": { + "sampler_0": { + "magFilter": 9729, + "minFilter": 9987, + "wrapS": 10497, + "wrapT": 10497 + } + }, + "scene": "defaultScene", + "scenes": { + "defaultScene": { + "nodes": [ + "polyRender006", + "Geometry-mesh002Node", + "groupLocator006Node" + ] + } + }, + "shaders": { + "CesiumMilkTruck0FS": { + "type": 35632, + "uri": "CesiumMilkTruck0FS.glsl" + }, + "CesiumMilkTruck0VS": { + "type": 35633, + "uri": "CesiumMilkTruck0VS.glsl" + }, + "CesiumMilkTruck1FS": { + "type": 35632, + "uri": "CesiumMilkTruck1FS.glsl" + }, + "CesiumMilkTruck1VS": { + "type": 35633, + "uri": "CesiumMilkTruck1VS.glsl" + } + }, + "skins": {}, + "techniques": { + "technique0": { + "attributes": { + "a_normal": "normal", + "a_position": "position" + }, + "parameters": { + "diffuse": { + "type": 35666 + }, + "modelViewMatrix": { + "semantic": "MODELVIEW", + "type": 35676 + }, + "normal": { + "semantic": "NORMAL", + "type": 35665 + }, + "normalMatrix": { + "semantic": "MODELVIEWINVERSETRANSPOSE", + "type": 35675 + }, + "position": { + "semantic": "POSITION", + "type": 35665 + }, + "projectionMatrix": { + "semantic": "PROJECTION", + "type": 35676 + }, + "shininess": { + "type": 5126 + }, + "specular": { + "type": 35666 + } + }, + "program": "program_0", + "states": { + "enable": [ + 2929, + 2884 + ] + }, + "uniforms": { + "u_diffuse": "diffuse", + "u_modelViewMatrix": "modelViewMatrix", + "u_normalMatrix": "normalMatrix", + "u_projectionMatrix": "projectionMatrix", + "u_shininess": "shininess", + "u_specular": "specular" + } + }, + "technique1": { + "attributes": { + "a_normal": "normal", + "a_position": "position", + "a_texcoord0": "texcoord0" + }, + "parameters": { + "diffuse": { + "type": 35678 + }, + "modelViewMatrix": { + "semantic": "MODELVIEW", + "type": 35676 + }, + "normal": { + "semantic": "NORMAL", + "type": 35665 + }, + "normalMatrix": { + "semantic": "MODELVIEWINVERSETRANSPOSE", + "type": 35675 + }, + "position": { + "semantic": "POSITION", + "type": 35665 + }, + "projectionMatrix": { + "semantic": "PROJECTION", + "type": 35676 + }, + "shininess": { + "type": 5126 + }, + "specular": { + "type": 35666 + }, + "texcoord0": { + "semantic": "TEXCOORD_0", + "type": 35664 + } + }, + "program": "program_1", + "states": { + "enable": [ + 2929, + 2884 + ] + }, + "uniforms": { + "u_diffuse": "diffuse", + "u_modelViewMatrix": "modelViewMatrix", + "u_normalMatrix": "normalMatrix", + "u_projectionMatrix": "projectionMatrix", + "u_shininess": "shininess", + "u_specular": "specular" + } + } + }, + "textures": { + "texture_Image0001": { + "format": 6408, + "internalFormat": 6408, + "sampler": "sampler_0", + "source": "Image0001", + "target": 3553, + "type": 5121 + } + } +} \ No newline at end of file diff --git a/test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.png b/test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.png new file mode 100644 index 0000000000000000000000000000000000000000..ba7a47c7fdcde32fbfff2e1fa12299e09753ef69 GIT binary patch literal 923282 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 z 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

oskh>(c(eYaf5LbL?qn}w6@O3F_mF6>R zsIpo6kxx&4dHS&M4ES%=>)g$m((+oaHnEexF%;WoV3raOXB|qEvsP*pYNeBC$^q5?^`q8-TbqrW3)3&MMhxY^(>}Xlc|` zzZAcj8ReV?$5pMScldiBKJR%9*r!G~3fGlh`&z9qJLcIyTz~JtFk->Xd*d{);J|YJ zx!ecS_4cejN3wV6Tj#`pKQYC>^*b34z8Hq|i0&*K*WJBR*xAyo+6PPiE!V_p{cSXH z+*XTSU|E2+HL~%61mJDQeBsS#DG%^79_qtqFoVYDXqFOJKB4fGODxN*g)H_KDmhf& zb-XiF@KF9$JZ;c3&PCP#?j9|6Ix*Yo*E|Vcw#hZxE^wx#wgR>pn;yqz>Cw4rfE9hu z_xIk}=4_QT0j=fbY~Uk>i}=-V=^_&;lcqefnRuV>vI|KuQy zuy=AK8Rd|S#bqqsyM|ML*1Ge$@&b4YNu^}*BRcMJMqTNGNo|oYr z+|*kHQWt8>XSCKI7^s#;K^-6dQhC{u>^S$qc8B6bSJR{046vV`+SkKYyp95q;3d(1 z{!6x8a$mn6d( zeZIdx{K>iZ`}N+>=i})?!L=QVJ}%mos_J{*kmfV(dxT26QyMnzwOe0hV(52vdkPWw z0j|M0=$LjCgQnJBdqgX2%zMAYySneFkw zoc^{YU=8E3T=lNTJrq_T0R$}?=g7f}P{t)b zNw&U(BG2Sahgn+tKoMPKhx1|BITda}saSCP5c^s4Xnl+Aph46%K*r5>NJJp){UAF+4Hvt=ce1Ol(x~qQv+&8DQ&Mv@%Q&{k` zt`gyDdIC8|Zj588}~8rKY`$6@k2Cp4*2cGj(`az7dQZoB>U z84tpQYIlsiMqyn1^)1N+>C53AiFyFaeV|sy$qK7y)jM0l-aoi5PoUKsqQQX`4rMQ& z!LhmXfL{+Vu ztm!b|?MXf-7B?YU{PoAa(AfUL#WR{AiZ+vB>jM0(?%adeV3#xSpl&p&Rl-RBhw|Nk z(AZ{jNCxr1owT$oTYZLIj?HqTf{x6yMr|{LR#MIIJ8>Q2irm{bhcnKrT66WUiLEr) z_xU|V0l~vW&HXN2UM?gLl;`JvD_#43Ac+4{?20?%yDnqn|^ot3z_OWQQ9sMRj5<5j^E0rP!vj`j1sra;{l$B{}s6w1#Ni)wK^{d%9 zb4h8dO!Z$$j%!mktMn#jE)V2ou-@gU6Wa{qx(i$X!>l*?;sci{uS#5eDsRQbfE@?U&V!h=QFPSwn zbY>|}vdT~Zj>?R4+JyfPogl5^oK~Oj@MHosz+Mn^s0thPyUn@M8$7xaz998o;Ki(g zS$lT)*+t4NQDDWsI{S{*$V6fa7Dz@V){@c1kBok}=Ds`R52Ms30~)@^rxt^CjWAuyKms0mhT zXm^9fN{KJKW|X6WU8&KiY#Q|u_bm^_V&8-k*EKymI}HtY(%@s-&7Yh|2qDIXczo1w*qzWQB;ZRoE(W4KetX}QXb0(hNJPCE5NldKae13%AWGthL}xUp7?fbPSw!kwL;>Wqhl%)2le&0)^zG~7raD9uCf3>ymJLo9qNzuKD zYMppGM1;^zyWhZ`GC>2b@|YZlzI?@IC{#Rg{~6D3Nd>Fn$$M$hB{9AQVkX>p1sznI zo}9^Yv6xA!@vxM!4%onVAZE#95DSop4Wt5G*#^O7dNFSIKFQ~wvk<)Cv_DbQ8%J%* z3X|(o*L}|1W23%LM@QE9f#A}=wKXeH&Ut!`HINw)u8hSY%eUOYT7srM*36cn<5;*`M!b-;(AvLdhNj16`Y#z!W3)=x+IwUs->i#1DgUNf3ov z*T2XdvB#zj|g?8(3aP4qf}hJX*q9zqn9O(0QPou0T&}ubtqO zaV>~wzNhy|!sND@U>ooi1E64n}?d5uIUz{{vGlmw{ z(;ZJv?G*zg3wt_$mnh4Gbej=#)e=+al}d;YpCPsO5?25S@e_;O2k~=df*s=#qN_>s)C|ESSupvo!YPljaUGu*CxN<9ZvDQ?lp_H>~WqsNW zU|6Z6#>E7?Mg#+0bx`s;C>L&_;)5}`K!}#wa~@FY04ka=@E@YIKYi3V(*{`WyL-tZdkEV3XfZAUuBZ2*< zrq=hmX)SScLqt7%kguk4UYIe}hL8LPtCe3)af@v#f_QrH7mPa0a0riKOap%e_!hL3 z9cvaEtMNcLm}XnE$d{yGv_e4FJi))%fSeAk*xua>6w9gjIW_dYMG%)2`sr(RgQmPTnatGhaZ$O z)_**VlChqp0p+{S1>H0e?L*cKsbMd1ar&*Ov6GH5)>c@7Dtgi1^TncAXO(SrpDDWB zGct_ZQXku$HT$Q0dAz{#MBqMxV zTNgLq<{M~Ps0o`_90y`mfs|k68tuJb#nv&G^Zuln;Khkj@R`}`UMlm`C0Qo9CeOjXA=R|h`rxvn900FW0xqK~KndzAfbw4} z#Y34YK#LQ_0DvOWk`$!FxM5o}}5=LP=YSa7v6{~zavNbus<3liW zjVF6GQSe0G9J>4iSc&oVygp+PFcb;cYN))%FSPDy8jK%rq}rZ_| zu!**=&MlRpy%e&R#YUm^KB#}ZBra${rp9_H^mf~RPaLE9HgIq!4h%_gj6(y|x7M$r0-|3w27isO+6oIX3-=K2ROP*~eq(laDP< z6(~H-h0Fqb6;<)%EoNFLoZ+;ac{!m5UKYP?97zdJYmg?9uT99zYRtPV)ZePz`#nF5Y0aQcu@YghpP=EjCIE=*R9)N|R^OOHLTm2~wAtWyp^sT|4#3-tYbMjjpgjmhYfza>Ix)6A;L`l0@GP{zH;nxPy! z$N)$y2-v(<;?^hjgU)Gv*fH=~2^x1zZy@i+mP}UYjrp&M}qEii4V zIu?zYUDv?hprVDm(&3t=6OI|08Q;T-+5%$H0%^)i#k$i&XQ{jOlh!4wby}uxWQAY0 zFgWisYwos-mew#I%B-l=#>Pbq2F{0A)I`DZBBe$CC_eRSR| zYUCpFdaq7$?mJ)g9`6@ZRc{fUVT1Jvl_f#GlA@Go!Gp^7$#HIeas|GM^Ko-qZ;45= zBRpyh){)>^fC^+$cI9j+Oc+~A;@P^$F%gu~FOORCEs>Z|c4mC)QqPO;1a1NaWB64V zYDj;4SGsKLG5-6CV4vM=U=X2MpXpOSGXcvwVoD7UCI{{pNTW63IYYNRv`1upuPT4X zecY+u?zQ#_Z{}m<*;;BSYWJ%DYwgRAJc1Sudu4tmCy^#bz)xeY=4}ue+vTXcsdAPd zs|kUJq309y6)akP6;}|o{E6&(rJD@WiYsWsQS4O>MOu}r(fKtsXF=%a4;62L6mU5} z`5U&=50}zvcwQ$Z&NZpJ9uSTy-X*4{FEDnp7lGNwZ6vyN!W>WkZ81yNGT(0F8#rH?WvGj`#0P_P50MlElv~ zi-qkF@&K%W@-Rc6_iukTxZ0TQH@Qh9X*Gnmeec=K&`Rgy50^qdDU+=pxYKVLaj`y~ z;@+kFhvXx$KN%I9&c)jH*6NT?PPZC8EGYk>J>D>QBJQYlvE}x2wXwB=!$cha@1KQ4 z?wjrN+EL!Z{ny*+2q&7x$$IpAJJ4!VlkbiWCoaTyYy(lb&tJ0si zBIsD9rM+FAi)k9fvT&bh*?U_BpZ83;SfSd zq6I=EQu?cISrH$Z-j)pqHHSQCB1kbbm=3_f^NMWr^wL=T+>7<-`^D8q-h4rhDkqan z69*{g5y$nJf6I$bSDXME4V3dQOUI6qIYL(y2-bvr ziQwDe(Oo*N``k8F(G%S8&+KOclr7I7Ga@f(jePy7=Q{8|ge{O0#GW+rc_>Q^(Z<0s z7uKojN4Vku5227DYO!Jpo?-wUBcU)kHLF&^Lv(lv8AS3&FGO$V*COEG|I9wFx zGw8F>8r`lp`+A?&xVUVcf6B3~lN9$Qov=|-1V0>wD2XZQFfbEz%o+f@FvXN0?~ZD_ z7D%Ce1YXW+97NT66Hyhj`y6mA(r3+55;lj0Bo#?Fh%OpUAKfX@*Xp>Fvw~!#@aF%9 z&@x3iyf$xiwB+9dmI?2P&SucNiN6Do9@jF$D&Dh6;=SlgrQcdYaC;I;3m5m`BkeD% zV$CIw4ZUw#m%g^JgKPMCs+*g_gEyLZ0E$)-2a zI;KbQ@J|(^B+w{<1GU?{bgoY0`%=24Yjap_*yrpi=#or$MZPGCi>683o0?? zbN;;rg;Db7xDi{%voLL-lFw$(mcYm!gJu>-R2=0UvA25$i+pHrDzUn$m{A#2BSUiS zE!L+=Z~Np7gRP8oR1mQBJx#W%{MWP+y80L%ax$RNm+~ZLrxRfx_Uc}pxV`L;>xvbK z6ab5pXz}&lFJ97h>l>1(ziMSUo)qvXy#2=X=ot81-itB?_+3lZkKYqaY1vbbkPw-C zne*(k^V}=jF8DXlC-zV)AExsW><+5yF*WFc;5oO3Z_%}0(Vk5+0wZ$t8jXyy+@2jE zG}DL1%kOJ1aQIknr1!PK51-d;30@7jaPZXf3tCv7ylUBYZGuZcuid6yY<7}qr-af^2IMt60qju*D*OmLg3qM84E|Caga@a@ADi=!{}IpAC(V;-%i^bUhyl}vTM)8Bb^8`vx|2040#E_VG8krIkG_8UggfS%JmL{@nG5*YnEMRQ;A z%2QiOYGKS@)*3rVii+Gl*+}lXp!F}c(`24xK$V{^^WSV9+rzt~i=JvCU56}Ai#JN8GtarkW zHMNCKlS2%0KZ3M$0H&Vk?V98wMcHYzq>yWv56<$hMfG||*FG}m_GszOGJ{U}zPLs_MN0HEhpJu2xyq7O$f$>KtDb_`e2eiR;$Yi!yk)H#cTfGHX3P$6aa4mhW zek|&3#0e-}xh&atd5*Ls%()09Yi=~Q)V}L`)q8EXH5otlAsTM+^s&qCLKVL^gsT7& zz6e>T`p+(Tqe~?m96a(f8ZX4hDu%OS)w5=65rx=G6Npr;OK6yO56#WAgj`DLkNq?Q z-AJ7&c1w~GgsI!eQ7?yRJNl44z*%d&!L{P|6`x!jWE_^L=*hlzerSkxCSdmAsCy8r z4m%0n5SMUBHcolXH4*yva6xm4sE78(?iLvw9C3L!B$h5zI zWb#!>?~Ai_FDW8dy1wSrv$$H}fUfl~B`h+=32wPfMJs3{uKzOHW^bWgYLLnCMHN=A z4=v3kx{mMyGDet{?x@#B#V*L7McE;RbEW#Ki!e)ZuVzm@M^z0KE;)SCBFX0d+2@jf z&E=fHs)m!~lAU`p@F@D2EXW~HI$_d5dhK{)rpn14soavwF{b1>YxZYW(>H1e9ts)L%Qk@iI}X?aF~C0oYR~&_!73YG;1kMoPko z=$NUrotCXXn-e)P^D}+(VIo#c0+dxP@5pMbKO~K=U^NJ`R4Nx{cvPR#AOh(Ps@8{D zTnz%L;MNVZ9$5Zy^gLtx1M!AAkCF-^bq?7@1IM~aG7wFJ0#nO7Sl~Z*@b}h6uXt)D zjF-1r(Y`X|UW5q8N0zMwVede>X$H~)a~>DIp{jOn7c51K(>>;Mf(mpIea;%!yQ030 zlt_Us02b?JhM$G)w3^&+uCMmy4dokIuA`5CpEIlb7=1ymJ07XAy;R!pO8FI&nsV)! z=jWqq{9XdboVMdyjWCJu#xAAvfAi|{)8@D=@R2&5S^%wJ!RoV~YkFF{n_w@cqQRs2 zn1})o)T(K4UD2k-{`aig8h6_WJC;&1{6AoNsW*l!vl7esf&KhS4kLS&TZE(kV-CCE3*ta;#XNaBZ3cj#!002?xfyc<_kgLEpn+R<( zu565&Wh}q(vFZ1K@OjUoKZEbo$1>cUJjU~iT%MQ|h`i(00P;TnzP3u&fxcfhSo3_I z%2rVDDNJvujy<#>VM(YBYr)rMacbI``~Hn^kbi~yL>lvqJPo;&_d+o!IQ!wYF7C-k zY@B$0?Q1iM3rxNhRR?kTUR~}zTZI!(HIkTc=n;D@n!EB0GI>K!vdW^-vT+($T@#|; zcjvsQGYKzcrLcA-9^yk_>_e&}^W(3>uN9u5f0b8x6t(8UHBH^BUt8I{rPp+xJ^M!j zTq_j`@jVi_qR4)`cNqo>#9Zf~!Q6Ho z8=0?xV^>J=HGQ>ZA(2QNc$2tqG!i#aH7Unu*wQQ}98EqWy|J!JBF z--UN@Z36OVwcyA5#qTya*29P5s!OCb^CX&Arb4?~S|HDYHL(TE1jTQ4|1efSP*^GP zYmYX^7~?C8HCj1gMHvq#jF7xt!;bM#g-QRRs$icGBa40i_K(LC?(yO$A!eu0%b5OK z>`B>(Q4#36!(P|!mzB_^-#u+Ssq4M{Txmd))LuSs*5Vc?zON60%`LXxG#GpYh2*fN zw8-w88(1!+6Zh;#`%19stGw0^X zY5Y=gI+EQp^K{B&nRc+x&6KEa;9fxMf-^WuoyVMGhl><+MCJ%LrQ(?s))gPXzh+5FceQHL&Ri;o2i4?T9 z_4_5Rde<@2@CA1$)g^d@mC^3EWclr^_&J_tooy~NJ2F(yo9F+{x5->hhJN~i3-~rP z52`49F$9yXC8p!XQSh+%Y~0`2uyweDM?v@~3u~1x$6A~MWJA-JqvI^oX1**=2z4*{ zoONp5WstsXldS-tY+;%Qiw{xz&cD%iqZ;WO(f4Z@={05-rL+PYAVPOjW@`CgSTIhv z%xp>v1^zeN$95_SH>%#KtKiKP&(VPWtUs>1NPG$;!urWO; z51(>WyR%%4PL0r=mSmkm(veXCnbv1E!C7}a*Vq^lFUj?-_%+{@? zCM@{nXXl!t@|0LzN-1VepoKmKk`21c@OTY6N7rR8H~fk2Y1d(LnY2LJk;(8=Auod= zRXF}hk453!#M911c#wzWHY^p|QAVLz>)99!y$`Tz!EQ_CF2}+Jp0=+f`$uuL98wloeyNj!pkrI?I#W2Mw(}yMLL%G&bX-R-(Rs>Oee! z9T(VzvO!5J)_FD3v6irR%x%v#?m?*6OI|ww;GeX`s?*;y zc*(!{RQhd*p?$J215H^dE#myx!`coZX^4LM0Tir^mcN#S#Jbr$D>f=HjxI}J6XLsh zJ-ALmh@mt?GtT&0_YD5o5^A)lA}?d+b%}$`gL!8AvTB9pj+^4diQw{kqO6P>QEFCt z(~Ua&ZXettcQ>K4-sIB%|?HlMGIXNEWdzhMFung-DX+`q#Y^ zq9$w+_|Pk@S~>QoeeAAG)WBuc0^x*|uYN)ow7T_4w%=Ra!w1GktmjJtXRN4R0XDb%Q9=1{CQNO|tL~zaMCZ5tWAKdr3?Y7u4V+G^=5}&=Ss&StnEbz|NK+G$(_nI3sM-;&$ zif;Kgy+@iyF*4x$k#4M#PU!nZ4L%-JoeC@MVlxbU+I92zJ@xOEl}SmdB{~gY=66*O zlX1pDXZxxeG&nYz>hCYUMm{g+PF0SpTwiaTxPqP}MlB`C+etXI4UWh-v4VC+t$IHw z3i3{OeIhPvQR($T*=rqrGAgE*>9e~_Ur2M$VrP+*H_41{%#_V{UU4JqREAbG(y7vm>CENYiJQA&qcWUSA6}s26gm?6BfnX%OX2vqHU|dC>_M2r< zC_*hD_$wsBH`t@e9TZFkur`a6&2u#9--uXtkJ^BBn1O5JlY|*oORBHDs`*HPNi%b$ zR{>X6#Sy28Dt*)~L-h1PQmCNm_UY5~23lpI$adsyjjMyP8`{~mB5mZaL!=Q&sVk~E z_MW>mi+3?La++kMLXg_r!VKN_j3t5Iyvfb#l!T}^h{qLvSZl(%pMhCxOCs%5bP&ZC0-wVIj7 z9QZpE81<-#!g2SsHeA8ofsaX4rLiL-L-fyy%cI}37Y3Pw8^XrCk}`c_6ghx|EV>Ig zi5o6pKCxn7&n;$mvrzDPxCAu0r+!|$(9`jT-qm)ll5=wJ$gI@axiZtv#Ht#1RBk?K zBJq01jS6PL(2R6bEAd$j&3#&%(+}!RXXP~tkGFa{vFG?xfb%6c#?lZ@l|?;*E8vsk zO264B_E;ws$}F(H83xhfGPtYB-{so$4{MFIe%$CIEY~%Wek|m_nsKY;GY;R67<)HB zJ|l`us`$1@?0EX>w_KpL+3d}ZgD2?gOJ`m>bBHWb1lFM0xc@bNkH4^wciH4jXi9hT zX>aS_$EW3=LDIbUJHncl_-Nb;=_#!PdDFPj6ng)eEo3XRrkWxL7v4liBUYKSp)MOV z-`wDg%ygVDza!xiiW!4XI-o%ejXBo(>WyLX%&5%1f`>GFFPgH&5zfO4Nmt-4o-MC{ z&iGmiVCSgNpplI~H06uiK}8QE3kj+(Sap4+OIi*$Pq{eyDYaO-+!o63`pN0FI6c~1 z1rCIHUS}&Z!lxOzL*;q^tI^YYBjx*T;VYli3o{bm=?Cue)ta1)Coy`*!r3O=nBFcd ziElbN^~P|2qfc_Qg%*T*L2SsAcD*pAc4G-og_gEWCBaS*Q$3K#?t*bvY3>?h_EnmA zs~4i|jMTd<_fW=Bb}QL^=0vt}Lu;w&2S{fWg15hQ@Kp>hp-xy$x6V%&FLRiGbuIJ#s&71j zU;KAo34jk06u;m6zSJi4-aCP%cR8jMD`h5co)1+XBwf{EGCkffy2Z4ca{-$|JF;k~ zp6Q~^V`St<)uLFf1bnTPlA%R1CL-qG+Y3{UVvc6FTN=Z56CV?1F2F~~ea|NkkgxMv zOkaY=?1ucf`9Y>FNX2YUVaFf^TYF%)5zKLK`-h$Ga2Lv*wx?e`Ap}dl%re;t2W1N< zz4&7^X_iuu-~HhkjrfEVBXIO7`?YAGA0VdlRWYNLI>jXDRCBnY$w7f;sTSf|*Tdk5=tH%ZLu`juNG zP4wfWmBjA;L%j)0?05@h=20+iPT9$sp9*jQ=JJ+inDae3nk$ERqnwPF=64IC?jySerM+AS)=zQL2p!Hc^(~e zZ~*K}K;_A%NXOf#YBQErWLt?z+%ewN`3;R)WcOQCf97uQ%&3)eWtO^4`DV%(asR&~ zP@dQEG{X2M!0kpcJZ(F4_U@pCD-ZO8;&Pv~$&8HOR+PhJ#1c!rz-|8~Chf_YXZ$%( zyzRNoKsz8IaXm4fAf5PKV2595f=+HBEKYZgSw))*L_8{B2g*V+?lFqvwH#A*(W%y}<;Gnc^ zQW*+qk~2`0BY!SdPgf0PIk+AVFm4lMt@D);%q4;G(f9tubyxo$?pNC_dhC8@A-MJ- z|HSKnO1+z>6Is%+fos>dftU|Dgmf?1(~~(+r=$c5E9u(FS~p1ZN}UP4PxFnQzNqDX z())oqfq-5}S@H)L-Up2u>#(8&2erFXR&Jv!wRYS@4TrPNxgkgW{4OK_EOp6Vyg@(~ z92_c4;w&fdyuEC4Aj7C5bHw=)9{3cwoJfaU%&~PP`mzqp8jPZ3T!UbFM}2_h@r{7j zZZRNRNG*Zfckv%=Fa*lXnVM8b8*)UG(I-4H2WxI@4hX)HK&$dO^7o*x26k)LA(H6t z286t2&(R*RgXqCDDAMvVOrqK<{d*FlMD1#Xc9jB6S->>d^N<1JWS}DTzWokX+utUe zSoh34WkJbsr%dgkZFd!I^M^bx?UfXTnc|Wv-WoOKp-JDJ`K=`%rRO>*0mp&JSaSDT zdT%9r$aH>MMl*0T1gbskR_Bu*rJ8&SseJ#1{uJyt0Om=J`lyV#_-7I+VixP>KXrc} z^kREo(kv5*WU5&;1=_l)k2(Xahke7A`d7iY==^hd5kH>BS>uWU4*!FRx7F~dV-Vf}>-62~*N-HJ<(w}4Z6k5cvTEj=g`-7>uX2dl! zU%N@=3d2woTB7=idEA)ll+;3@=4BNDmwWhb|x;9=&yNwwA9A@0A80J zEto{qplc7|9ZuwYJJ<~A^;+Na+u>lLc-8UUjrf`7T><2H{Cbq<&5Cjb)^}}<+*E!A zu*LMAQ26slSPzcGzo!K%uT%t{`0@qEU^Fv6JTcCcl^UE+u#aaZVG$vt`u?}D^v-+Wnxcrk8CLcG zUXRt^^0a9U8&zMTLa4jJ4>Oww$y(j0b|l{j{xC0nvIQRcId8_lbtVyL{_unrcvfz} znUfw(BR&e4tWG z&K>l=2Z7y0SZZ1~W+cg$+`GqU1*K*>_W<4JZz8LbWtW%}rf$~L_gpb0)b?}Axuq$o zm-*zs$1bX$iyiE7(_u0{f3Qz*$EB93nXX;NbA3R&Z#IB3oZrq>4!KmCt@XOqN7+mM zzpcm9E5sq`(c~Kd{3a76O7FYCrv*hNx8L#J*=L2QS{V03T*~JuzH}FL6;R$qt48WD z?Z%tll}hD9IP+zy8VqgBeId`ssNR7x*-e@Wr2I^ZBWctDS41|=*0q`ZgZ9kf-l}h~ zPqhI!t;Lo@VHyu#2jJf5U$H=P#~qGAPulWeA=W0)m1sEm8;PTiXdB~8u36S~gF*Q6 zzO9|?2B4mm`7Sd7?sb$0XJ|@ogGMFH`pmB}JMuTrGwW|Wn}~{jubJO3&(*Mp(P@Qo zV|JKyu3(N-FrbLF@Iuqx+}ds@PjDC`@{ z2Kzj<#-=S!(krmR8xwNIsPXBEcq$l;CS8JTbGb`q=9C2j~lwARZUIaK@(nB5oo%IoUM>1M*(n zdqfeiWhtYyW$DxOe}`AHANCfUqe1A(O!8s}iw^~Md@2X8a~c>?)o-VBCuC5R*xd)9 zK_Wo*_EdY<%gV5Drw!mk)X(^!WM3*}{UfCNf#-z+1loFsw@p(D5 zxgiW;3t9B*SZsfL?R*uqe0G8ajAZFd#M7Q1f4&L|a+OYH(bXCn89VVCUQP00gUqT2 z!$wc%Ygjs`Xy@HD8^yn78`*G{83jl2hr1cZFe?A$>!WP%^hx1!oxd&1EsQ{ZS^W7J z`@?h|^`8neG#VN8_j>L15(L^r@hbQ!rfAHU{NCe>mx)$wOw$!24Q6vm6llj1VTBuX z@5!Fh3~}I&(c&cynbfFTHR)eMz>+j__x>PySxtO>?h^5QI_^nGGhQr~S??LAV+k#63I~VDi7a#+ytRnDs&vr7I5xRqd!@BQv`I^o>FpU0^eQR7^%@VrQ zsHtXULuq1}fC{qAxzOsh2l(pOEE)Y`t_vUM!YgH1x7s(`=DwU~gvk8b&a`p;lDDRr z;OU;V#*$mD=y|rOdD(iRA2|Jwq5k4y7R`CBQtQ8jtmNtH+{KUWeG_G$0vnbOEm+6I z8df)RmbpLuw%){8O_h&guodSlRGK>*0o~)u9;N@yD23ax_#Kw*4~TE#LnrUioB0q? z^K}K330)Am>bF9g-QyAZ87s**Nn7H@y_J1qc?cQ*aZn*bgkC>)V(fXFxRFuxGn>(( zU0R1bcAS6YURvd~67K+Z#()ILJ?VsY zV$k}u&UK*AO8Z@&ARZz3#!`W9{m`p8HIW>>U<+ zDOPd_OAmob9qHEqi*`ONh0$pJy(29{smmUfpqQ6gh_=6kt8J@EalC1h%oyL4-r*uy zSv$39v2cJ{#n9FC_3hu?)H_PcDGZu8dijEWC!aPeHc0Dax8?at2RINg}M z#VgLmGOLSy`c>s`oQBYUj4CE@^p&D9lZ#f5Xc-skM$N*~Khr!C(Hra!n%o3K=>r_*@a2jNrL-M=#NVpJVsr0;M^|75xUp%2@cfu_=oXi%Uw3sMqU3Sna!D*XenF z9TZJ*x!%95KNZx{sCguIKi_%}H?A)0T9EH$e!h?Y)II&Fz+rSl_PuAKlG;Beey=!w zutAxwT)*;Dw|R7=a{T!;;e|Rn^CfT zz;@GZU*rhIo}8ImVv3pT3tCV)GovR_^o zgc>um^n(dL!YC&+!Swm(0k34!lQstto1R-1E54UlRmC&>I?(-3+d)b*fZ&fKN7uv*FV>x791gR^0Ghe=a5kNiAV z$oizaDSY_?`Xd1#YB!WL{JXesviitI+QvymE%nfhacwwsE^%2$)7;|CcxOxLe%EV@ zX|q>eu8M_{mDGo8LRW}2ZHIWBz2@uK)5ZW#AjQQc@ODU2N%VEh3!o&v{R;J(t8U`A zL{QW!bn3#t^v-!s+1=sG(9<#yvJwnb(--G!{`z3;%v$(`ne;^V%W>oKZ}tUILu8%{ zbkKYKxgUSFymEg=2%H3-zItM^(@RPd&l7jtp+Ih4`g-zgz$k?MHF$mL%7`QN?0ydi z0JD3l{)-Wq=Q4>178G^5eij0bpn)Hg>hv^p97Icrb+%aHBmrX9)=kT$S(fbQ+fonj zyYEZxq2GE`)j~9l`JK$@Qj$E^cTG%AxZQ3t6IurRCIfU$-~(b1PvLKisGtBpL4ltx zxftG^NlMnB1^0%N!t566_rLmWts3W)T3{M5{esJe=7YFkOgy7{*PtmGeeSaGNd6c$_2rROg;nOMfch)!*(66#+8qPKVgt(ci=>gm!A z>r1o`;XH93%smz&bH4|2XOikKX=Nom`70(w%&fuAu*4$l9CESOU~HnuU0+VZh3o&G zJ*XrXN5I;Ul7n@#=>&ExqgzYxBdB_bfg_sOv3&CY8x5INk-EV7mc%`e1$y@5b%}c# zvESDHH3j`VFd>1oTr<3rE@>E+3-N>IyiS^TSbbfwLnw0+$W zCH@@E17o@?Yf2}(w#edY6kp$gpgH6I(z%J89^t2a^3I!6!!jR09ipb1Z|pOdj}Nq8 zS$FDO&wqm`ZoFROPTmCPb8C@;C4H~+pnI!FcVQ>R*1m&^EiCp6ux2Ue8^?l+{5u<* zcN07pSACB?w_+|{iS&jnelAz**gY$8yGPKCi$S~X#u3Np*-2rvtutoyZyOz}sMRHI z7Tj?+I0;kod$}~9qpAzzi#-@9R{yf*f;hAAh?QZiH?OMbEiZdtk1%rF=5GhyM;C6m zUU@nA7pJ}Yjc+p;I$xx(Wusj1^cc!oun`N`dFyzJwt9$rX^Jw11k%W#rr!#AOb@hP zo_*`>yzBx1&5#4P9(hC|eP!$Wrs-wz!^Ez#o24I$F-3|&;VgtLul+P)Jl1}%aqgtv ziL2_ko}VXrK>12ps}0*6&6B-l?U7Cu3~Cay8S-5)YZ;DrBS^G{vliUJ--9f`f;(G` z5Mr12q15nW-flv|c-wnbb=$UV@6CXf2(@~jld(}T+# zf|cj~U8BMIcc3gn{UDAt`>=Pdmwj?SuB!JK95UYQfzbO&P>Xp1(fEuwyTTLnH;_MZ zE)^LNY{Xx)yH3wvfEBjSOn?}Xu@3D5 zBG4KO0n)_$9-Ju(y930(;1ye<*km&GmC`#8aM+6cXkb@w$AraVU-7}~=Su)I!JnDz!v?@AfB^fDfJ4t7;WuUH9els4Fm*>E4@N52@OXUb)2s61 zjFiBEC}tPKiwc4-1^J{wzMlBXT`M_x;j?@<+KpzHt>|e#*(UU7xECTxBlu;-p=0iy zvp1Cyslk;x{XmMVjg{5PJ))fNzwx2hK$CWbUd=ts#{~&dBSZ^x5IP^<+-v<(`9{8! zp{f22-3Q><ypbVC?T&%y_m+HuJ z-oUWr@YEfF=e-M&?_X4jBsfb^5bl3!0t6viv5;F~(7#^?s4hEipf~kh8Vx3QxC>Mr zee7SKDZAf03lyb8S}KmN`ND>p0pO$a%jVEXAb@xIU+(qL1%Ch4KZ#`Vj}sJ&XKR`T zkKt6Ywq+b$riYx>zaNiXp{TS9uX)^zp)!MZFT|$NMTzbfb{0%WdOducUlYr8MEH`~ zid=Ze>nwQC_@CttE!RmPM5E`HOXQFHtdIjiNqeD?=OxQ?(lnPlW#I!<71}^S0sxaQ zkH{6zSO2c9tpRkC`90IkcHAGsX3~BPvGAzkc|rN-%8Muo=%_#&BtpU~*Kd;|N7^r7 z9)e+?GHBV6*BB~ucLMz7;3*tc<{Ar5=bvUQagsK}qoYPPa?|5S;a-7N=SBx@rH;%t@cmr32qA zzdOp)G|6hPueO(+YnN?4-c5@~kbvM>&m4K!Jau%2e7UvJ?C3rlu{UlMz0t5E&3w!s zbz!@}Kl644luSwTCbD7_mcMhZFGUDdoElhD&-5Ou_CDF^6@K$Hl}9eMx5H%n94=oW zafsgXyD}Y67AR3evrFYjP5Www?vRg*COi=;Td^#}-B>LTyDv=%TrN2hPA(!?g+CZp zD13UYgG{Ou;oa*Ia7e+*-)b!?pMR8Cvi}5dOL)j+0+gBDf9w1wxyXcOO$7{p?aB4M z3aHshoJCYq^@1UhiR@@*$b7)UlWVI{j8C0gWo+y? zuF=sqD9`*+vwfJNY+p~ohwuf`Kq1bm>N(8vsVZ2tBGX5NS}s z_^a+EY_P_xM((^4a0Yp>xwEdDW?e;*PzrGAwZOVWe)(NVG4q{t$xz+xyiryy#^U3P z{^Sb;j|gK=)9%^(k;Q9U(YGia4izFmz#7iV6uyvA|7WZ4bD1OvbL02+l|owK5EbIz z*BhwGhcshCD$ZAt%jIU~LJ!zZ1(APTGh@8=O1Wp5ubqp#Uv&;UEAQF0y6!|y-v3g2 z8iRZjgSxO57neXciH*PvSG0A@qc{m}KJDCVePNVd3e&|v;_Zjlv$=V83sX3SR3J-J zZ5us3M5Q<3S0p(?e`kl~p1!@d>WDI)vvGB{u%APZt^Iu`+@axjc;T`F9D;RIYxu%g zGd!t&Wt~)y{XREecnUpn7<8XuD&n=UlF*Q@^nkP0nqHMU>;d$kip9|?oKLeSJ!o<& z+_-A)NxEA%Amj0Vx-$f~4V>68M13lB+JrrtNvM)|ShXJJppusHC^?l@&F?Wp+C!rd zDuw#}%=H^-G;plBzv@I!;O-#C8uWE|Ye5>#{;f1vw(Xu5Qb5CYA^H;6*m<8oaYl~W zW;Jk~UKy`(NMXJ?Er8X65Sa6YObf=*3srs&r5{LYZ~tx>$bW%A5a>Qrx4e%vcg`HD zea%kNdKWglX+QBPWM|L#LrD7`^&%Q+Y5N>D%ARwjEEsctF zBi%W4hje#`gmj~HcXyYFl%RAD9nuZb=f?Lt=RAuatR*u(ckH_Mwf8nGPW1d3EFoI3 z0$k)S;U9PF*>48#MaHtwZ#-D$vMZLgjI;3EKQ$YPQyp$6J&277PJ!e(M37?X40#u& zUX0%Ut8AK+;hVy{#Xr8`tvZ~^sR(l2_wdnZ;1O5y_I-YfR0+Z_ zdm`$>wXxk^K~+qV?~&3zY=6uf{kr%+Bzd;La!p)UGX#3O@tohxc_|xDW-v;i{?5O^qWXw(4gV$B3Y5h->dB$9+pmU4;YFZCwIB^$;Z)cI5@bRfx84>Pku zwoDz}&mn9;WsL@8dTc&7ae7n$F&ZF| zNFHq3r$cs{UhT+M2GwdjQS-lrISi)=lAFu#^5E|dH$(XQC*it;k#r5(zJ;VLykXBG z46GWT9SqR$Na1=ZIV&Q0tePVf$628gJIqd<8<%~e3mqsQB87Q~)-@%ghBa}uU8roZ z0ov!7V3NKPdM`@b4t1PY@-ytFu>2aBl9Z{bsl)^FBAwkc{o2_!uPdd3AE&J!@l7wS zp)FeMnsj>VU(ml0r>M9&wrUKpG`-s_!Vd2&zcx}*6q0&7Z-G=V>>Q~`V?OZmO4xa> zX2beZYZ3~$BcOFwiK!)L&CDx5>EBIICksYp;>xzr25h+iqaAPy#C42H0?IvgEe5zD z?9p}C$BC0JVG+Q%y&uHRf{arj2-3iJ(Xu^}UtG9crXI?ND*)y@sRi}5N&ex?r zu>}P)m$hAWJ+pUZZ7Km6^2_^yQ&T+ zl75J7H9faR?{%lKR2j5AOE7>7dsc5vKt@^$!#b{?xyWk2imgS3>8D55$p@9O(pytc zJgj%B4x!(~>%_V(em!o5tOR-1<)UY$$3TleAF5N`!fglbot+};PnVK)Iy$YKC2CpP zr>}~v8Lfxgf{7HYENA%Hcii%4{fG#x_5c_`M)S)9^1!Ot6jHUT(*5%`6}p3YaZj|IYTvc-WqjRqGVs3#H?bJ zW_pcy_xBa~b}Hz0D(}=m14PQ})IYWM44;OoAdB=5Vf__UlAJfx}Ik=Kc5 zj_WCd=lU<5GF@8;KoK0^WQ^rd|Ij!;oCsr1$$khBKbP7DB zYzk6Ih`TgMN&908$%=aJ`sG|JS$Yb3 zc3!$j;& zF0FKTsTUm|Uk-FjMDa&9gF)rvZF0;h`>nb>C-D|u)O|0Z#$`@NW+Y^V?pDHg?DY2l z`}+Eh3z=%oMydk#PWG>hsatCgxydWHlP-qav(2Tx{(Adf)S_Z-q1V*o=^WD7OC%NK z+v8bW+QcM@81h1~Zwgmt&fL{dLN-(I!dC^Xsds5lr=bT8(H>d@effJZoR}Q^ojT}X z6$2smJNvzy&@J$we0-6-T%d%Aa!co&Ns)ErKq%#Te}+)W4+ajbgNl4Z ztvsEqTOY!6g9_tLt3a{LH^tBAwrDW zi{+M2oE6yf_q<(h2cth0RTEgUJTXh(x}-M3#}E)Cs79CjP|CCPkEEGIEF@up%*u!0 zu?92ytZ}=%KQoA-MI&a5Ed>B z&%bAGrQLM6nwC1Z{5*@NSl!3fc*lw5YP+>jL4|=|FwY*4m$W`YDZ4M`Ik(**YZF;S zt@dM1XR(PK^+dwUU4hV6fn}Tdnws%9BX2E+R`LO~g7;SMVq^jn1nOuCZhN4vg$|3*-Rh>=y;JLNM#j}e zbIKT6(1&4`Hz49=zw6{1sVLOXaX@xmh+x#6(?=l#+0I;MbYq%L?(u~llp^ki3(Wyp z_^>2)_R`|=o`R44gGqwv8H`^kaWq^h(TxMTIhdx9AQR2ru(8 zo=;ruQBMSZaG!nhQx3<>K%?wANvUEa2ren^MsvL4RsuJQYUsDSX2V-Lh0{i61NtK} zYn1h8{Pc`f)*G+)IQX-j-348G!LLILy1H((JcFW?2&Kl>lLH$|zJzCc{k@}gQvIrXRDdc|;EzJ11< zw1`Yh4FS9Ht@cQGxJt)Uj76k5?Nc0iR{E%!+$+(E+I)uz6?GrND`TY?n@Tw?VrnU} zFs1GJV!;NnY}j&AHf1H%tjXP8eNm$riK3`B#iwBjVaWyo9CwTJnprDj3Z}6Kf7cgE zPycKTePN;hvFkhXyRkAO@ieYIlK_XXEy9pnT~XYg^x!L~^i{}<4bZoF(mHw9xMMel zRvkOHoswMIBe_DRA-WRB$#&;E%-Jg8CW>EBBAY|sa`c(RpN@OOnRDm?@6kz(_aRCV_Y;_+k(3$-oc4na7fmP1P!nVAg4)(|(-?stA2 zhnWJtHYTek!JeN|&0;VjeSUQmM$V8k*-u?~QPK4z!bKkR&%I=bf939vi-4^?jSnrM z-uSdmV}qII=yQL|l{(pIloVbYD<<)yp)j(EBWjYrj@20`(I$=s(_d>JF%+%R@g|q& zD%6=IOM2cSCLPk(k@a;;45?_q>OQqP2vH%w0j{mvEd&zNZ+kq`mju_GDGdBJw6<@D zbAej!Tv8+7hM@_*>PX_*1s&{dE;g1BxUuLIQHH%vIyW(a5W>fZxL z!(K<>sE3grX;^>$={}Xi_9%?)2r#R%9~&>BJvVvkwf9LXZ0U!1d1wnU9Hpo3d@H?L zqS>ZiNL#Ql<}^jW;#kSmK)l*?P7*s6#RB>%upf)E>mlx%+k#!_ND#0ECrq3>KNm~n z>mHJ5J_4Xp*Joo#d;XXC$e#Fn&kPE!mdvf;3hX+=+uVW%1NbjsazDbhC!1SLMz9_a43zDo@rx& zl=H-az&y&{EzS$sq_F`kTWqfMA}_D$n1y|I$_wrD`N)&cprve^+h~+VMcs-u<}B{C zX_3%4-V;rt<8B0y<*;f()U}x%?-sV9pLxzz(ElvEUp+j6J$<1tanPxCRV*+=xp;4M z7uxjEoPNQ^+Ia!%`7bI61RGx#+!{z(<}Al|W=f?`sxz;q&SZEH8z;QJiM0ao&wK`f*=^~ zv0GDA80`yBOiflBlsCx}FW7|gog3O~v{aj=rs^Uh2DN(%GPZtJptYl?wK_T^esQ#g z0*IHFo9uDjkOlpZm4DMO_A(6(%+AHpAu&}gtCHo|wFQEg$$`2qMguESr={C9ynOi= zxpItiOo-SyJ9U)DHc{%VR+whYvE4Ka5-0T`s&H`^w(drau{w$v$sTEr9c^vvO96Mt zkYFcx@H=o4>fzYW$C|m$$HtP9+FS@-RL4MbOai5?qY8|4ZX-JxlP$npmixa!}-1n(-uuA){A=dSe!T{&1V z75HhXjNRAWYwD_b`BL|6qbo!rp>&_{UOVjOTlr0GOuPT3 z@zaF1PpO@B95FScmR5v28?|QVg_%BK93WO`49Z2CUzbS~&oN6k46oP|AViT@#g`v= zK5%Vh`EmTYZ@3sb^p)%`)iPMK%c&hJ2<#zMKC11UYYDZwU#vrYW-i+eeF^$%sGrc! zDkowT>4~zSMV3t#<*15cB^VXXg$_aKJi#!_{IzTr=#?-XvvFlbd!Btbib^isJ8Jhr zm0h~Ez?Ob40Rhug7}vm$@6)TJpe%Cr-k3a#L`r(29>d^bBvm? zMp{y{HjQr00Lf;5VLBpiP=A5=J+j!UE=9q@s$n6yu)~>ARk#o@Va->nWAVH&_C_Te zEd?#9#6MA{s3+3m5gOE=g65!r9q>zx`Op*j3|ACWaqo`dQv2K>K~6OHH(QvPgrqD> zot#LndN=y63SF|dTD-X2cNn7lr&9;EyMYA$B7KOvQuaC*d8xei9fdpD4RoEv>eS9U zQBd}wj}QTZ4gx9An0n%C(a_8O>EGzjXln!~$=^-u-@Fq|pZ`tfjsfQ!GSwJ^^OosX zPCrHgmsK~;<(AEhLSkYHWQoSs*Oi(%B*(xn2#+&iNPJO7U9g+8cmMkuf%PZTd;$@b z-wQZAG6-kC;YxX%No0wtS|{sRx+5~$6kR=w&_u*uN#bXi04A%_K8*uGRfpLL!k!zT zG?4j&MT4Xr=R*e!!}>=Nw|3sc`0{sr;86m+ycQuOr$h%;iwn6ae(fT}IL%+@%F6O# zQrB68Mo`zM!lXu9z@T2c8vojbFH0o;g;wr8m8Pnw4MGimqQ?MeP#$xS3E8clwbE^K zThX*sP+p;-|5;=ITTGx*4K3iLh?(rf+Z8#e2-CIq5^4bFo?@?#-aM)isreT_O`L0Op#juGMPT7# zNQ20I|8IW55<3zRx}D2)IsN1wZSl_H5$zMm+f?Cyr<_5B!M`8%xsa{ax>@6UqDtb| zi)^|o`8tiO9oD&#BnuMKa@_?h4d_cNN238Z#lduSYh=%4+@jmkI}!YA`VacD82$10 zYAy36_Ex_Go1qKo>Y(#S>mB+Z;`Q)C)hO}-& z#}~|yh4dhhvk0vJtXGIkU7hkyf4jo)r(C*i;3a@buxvQ&I<8W#AFL#)6W4wvwBKgu zY*TV6hT)a!RQvS))za-C)(AZbWkja=gpQtg)F35hY_5MdxUiYy{zDnhwM0M&M8I|3 zhZ57yz+~%AJKH>TnQ#w^d>KGYbUk!=&A3_6^2MI0xlqYpkmWny{McMnc!U?6J3U`R zYNR2i#Zv`C6Wlx*P4kaxjs9;g08*Daycq>=;`uCJutqY!U@)~v=CyU5(Qz5@-T#t- zRJuX_k!sZZQL6cal&s~hZ$6oPxnlfC`#PQjohvg>{1-|G&j@`u=q0Z^LgSdQO9@cx zb}-wlN6F4uU%!zU=ilI%soJ8JC#v;U0_9Gt}66Ggk7F~x@wb_v7tBdYy_uWf>VsDTV zAt{V7i-7uiJKmv8BQ^0DMw+-?aPRk8sy$RpzpE&%= zg#qWfR^3aBZ;1pZTd`6{JRl`K`Sg-??_S56)LGGsV2yK3`=O5jap{6-r0qpm++{ONJDmc1_B(yCDi>T;>?T|yD`Z*6&jFsFi_1KGuGI;$^>$8oD3MY* zsVyn4Krlt`yd|mA?uPUV#l2by@0-)*0KH(tuH{ex)We%d9FK39tJCYM=J3YIRU2|#y?m+@Rq6Y?1U-HU0cY9;V>QDe+K&_v`yOx zUa`*as-9q^I7JS4Lr-P+F1;UCd(p1OG{pEz>>OIfId;sU-V3&bBEhB7!au}E2_oj@ ze!OmYKfDjT3)&@Bp<;OZa`=7G%w6`9^;HQ*Xlg>WY_?Bn+n;IVXR0qy!JG5`2#Us* zRF1c3wF*s;)&b~@Z2F%;%-m#0&!z}m{{{LTLX%73$KE2tWB*-e{jCG&HxgqTSWIFg z<0omPdik=NA1u~=ch>9Q^W_9LPP9bR8^(h0N>sT8*6Ea6>0hi@Ybu^s$h50b@gv@M z?JVGasyyRf_t7qRgZi-v3=7g!;HqzBFb5*z{`kz!WM%7+K|QQc66VH|PH3-tcE)C+ zhAy}q1e97|?|4F8ZVeYGP(4KkB~%Un@S{uT)!X(+Xq?E#O;W7kJZH-dDszL(`JsaR zM}_O4MKN79n`Nm@NN|IC46(MA4zatC84H&%uaT=s_(Bal!%*>*6o*nE2)2ngKL36^ zPI=6}7)YFReG+*MMvTontNE*vM}z?C-!1ir_CSnIKq5{ePJ{L3bsiTouB36(I*9G81d2`f{A9VhFCb`SSuOx|~ z=BG1{^*rB62tY5U0ykgv6j>v1$l%+> z3a&BYC@*P0addy6GfeW_u<`JK6k8AiVf{^NA?~|%cuQRO8q^g%_q{y4*J1r8L{{wh zg1F(-oJUa=vB4T8t7U%cSLVYXaRG`qlZyM_56Vx(+3{6>Fj1twdEINAmg`eQLDZ&U z6u1A8yjaqUl6c_mI}*y?i7-^4pWaCFR&-~vgqWhl}d zwcF^2ztLBs%Ei86_Ep7~7Hgv9Wb?3M-S!I_DPs*3T)SJr-sonY9Kqe6`#I*!ur*a> zI`J2%A`VvMAEuqf*%%dbqn%Ui+ldxtN}y0pjU%-?bHJ;{@&;X-|0MmZGXd?|aO&V8 zyr@kbm-USaMlt)E?hTz1U*<;#P3Cn_#tFn5PaW$mV&a@!>Xdql2*>Q^fmf<8UiD8DYh}H%=Dy0q0&u$vHFCfG+Txk z`4=tz-HcD#%j$ekj;EtB(!I5SS0Um%10x@Q0mj0^tGp)mvMIlBP?nLNt&*K0Xj#_+ zy|00TFD2r=1W+zOL?3P2BxB*NBZnKgR&;dQNMZ0LiG`Io2@;R~fS<@~YoD=0@o2S* zS<+kzpzWQ!Z~wS;fG67N{HAR#31rB?OppV-)(THxynT*7k*X_o;bEzky~95yh30%W zk8=rOagL2x3f*~brP?}y<-lQf_TJ|2RM>+$Qr|&jc#qY=I!Hdo8H8$uVNJSel(TEq zY);uVt;K?24?v?qC#r+DE^ZqcmBR~~Y}jgf^qb=?2CvFwu8NKA;x_)(vT*);cOM+1qAjs3iTaHK`kxyg7z!prT9thho8R~rIUNn)G}y3~rB35;(J(NfL6_UifW?|2rux3hhzY#J5m{_wcpp(F`t_zfwT8<5 zox5TQOao}Z*fp!JV%W9xjqzxpeq%3}(Q>l4lC3}?h zzw*=b>aA^5CSY=|sp(5%OQxm;(*ut%AxZC(zrdpA?urh9UzuH)(>veUUrHm{_V&Qm%?MRhn+Oy4&y6)@r;Bccuy-K?Of0i0^SNeTX>Es^lWDU{ zfowHuOv&$>Q}<*G;f$w+p4!FJrbFihmN81Gg==7admi-v9W7EtV`8dCC5za7;Hl?|I+86G^Thlte};S$Y<2sGLhM7i5_Yd81*Ie!$r z&$Zx{2u}bW%g~O`bZ%?MXo(%oj#nP4?8Lc!=0IS_1{p4w(oKv6_3XY&*_Y5DLSyQ+ zS7qFM`0ap*34jjQMh4qHNCK_0)>5WS7N69G3i{%OR?_DZAfynI8wydEuNM9>7YfRH zYK5#j^U#gbF>6PL(2b=E55iw#xfgD4)ais= zaSb$Td=EKDSnk_l^x8tQW4tXgTAUjgx;3T;Ee9k|l6E|(J1LE5(qNL+id7aA?w`-O zF&U(pA&9uZWcB!3?z#1SZ$Z^$K&uYEtla-#!YFipw4dGAQa_|K8x+Sg*CHGNL!k%j zv-=0K9}HnZrFJI7`%>nsV}F7{@DoiCKYQCphL4>Rs)lPz_s{X3a9&tk}8 z5F(@BWnteRhp5G}Kuh7$?mO8y&RYGlI`YNLH^kPMn7V|-LWMqO$1)`;U<*ZniCLf- z?>=Fx5N)2skJ&NCUC(Is?xk30b7*WNmoF{PUXypEMrg!T`7YZNtY`y9w|T@64HRWB z7|W*&F%P__s>JBxOEQeL@hEg#zdjq6KPG{L9I>j>E;NhATTC7gjwtw0-&jodEy~u} z(vC_Q>;2fAli!j8b||Ue}OJm8i4(yb^i=*XDMdqsd0U zlNU=|EGH;;R_+j#I&p{!Ern@fSf&UMpTL6rOOI;BDCg_7?21|QfhV`+ffsX(Mva46 z#L36!eX)nXhy@0YTCo$Jyt?ft2;@CUkFe9Anvx&R`}VoDQETusBO=%K)F=#3`E~B3 z*bnO248=RD%a!b=4!F3QT0L6m&qC!pfdjrG!_iEx5 z+4egwdktEug?S~Blk&zwwPC`)`TvwAk>hg0HBo}`uw4}bLXWM&c_(L&{E;K>&gxcH zOTQBH&~(K9^}}s-yE@5tvP{^+be}s5lV9l%y!}0l9X2Mqe=SrWEIr7IeKd(30FSh9 zJae(Go6%OvH)ltl>wWei6jwCF$UiIX^ncjgWkh^Dj?ZC#QChRZ57mG!7b&UjA?R52 zPdv&Lt$p&ixLWrwVd2%DF=b(q7H>6jwWAzI05sV5%3_}A_n=LhOw0^MM>vZt^P}}! zCOLWm|8c665jAD%*Djgiss4@{eNBZ0A^{3FF2hBPWThgO4NrBUpb)L5AEQ(`C}OvH z0vvqc;xpL`W<)0PRCgfmt^~}kgIR$qA*2`Hq{S3<#G&~`d`#xbj63gXDay#3^tv4$ zl2U8g&?8@krpD}|UXJsMQDBxkq?ZX55$0D(6W`z5-u?@0Y?pPb4{yK%=Lxks-16N$ zQ^l+9qE)D>{DtvCRrpd->*;?85b&2ZVB%vLCkv6{v2Uc!ez-b#H^jDKe-M*xW!2xL zJlEY%3};IK-zALz>5A9RD>@@PA*#~0XAeq&8MZD+%uVEP?wjSmP*!D0kfGI?Bx>4y z;wklK3)t3wve>1Zfx6UVlSrJD|CaXkf^8tci7uCX^)^mgYZv<&r$^!vY1H#LvsGW( z#C44Q2#sLKZJYa(c7?+czC<$G5G+Fw7WQQlR@eBmezwf?9N-QG)sLv^W$5t7+&?}h zRx^KmRT%Av#8DAUwSy2+h5|HJGlr#&_Y_=A4&G)DR^{lbxU`jglnx@&?hXW`df`w? zEmsqk5~&LAcu%eh#ad5g8@>hGMy)o^MtBuJ$Z~fFokf?DqQOS@!H6eed)?mtZkDRR z3Yn0KXCVevr{SS16#6{0bGFl5?}h&9otg&$=ucDu_jr(gG@sXouLuU;ujhBQ4$z@v zk)xR-9o+(84;X>>p)A)-LB^kOjCbJ6W&&>KmEOlbGy6WLK&DdeQp&EH(c?gz!|MAN zhXoJPU;yoXcPLJWHT!8$9;C)F^Yefvl)Z|ot$p7(9ZA$lHzHG)DQ>U8AhLE5SW;^6 zC4si-j{_0=*&hO=nI~+G<7==f7oM@dw4VBn@=-s8<{wJYoDdIeJmSCHe zH3=c&p?w|ew@_<+d0iw~1aK?r|3cn6Xk2Xp7hb2hvqAVP3hSi*F zV6sZB$I^5$x9%Y1sRU6q|5dYq%T;M0obI)|8(ya?UN5GNp%iWW1)h!AL8&?S+FC1bSDp z+rsTdRI*k>V=hXPvm_;p^5vjdBh#kVk)8I?*Q8_X?K86A#}EvSRO|So^GXhde%M-l zo0wgzeVEDhJVtwoSogg`^_5LWXZ-_t6(A%d2tJ<%5Njy?vGO2IV9) zIs{OlFtP{OaDT8@Dv58K`o=F5Yxzr5#OC(l$5$V5~Z{0wIIt&00U;D4766Ighlq0aMO~${3KT=>}n8! z=6)k1fU~^@g5`&dQH*FB0@0w$--DZAoRd21H<6=4rWYsWYFFDT2;L?LQ`mZOez6WE z@2~fRz0v{0=1?EuaL{@Gt5&1rb5W?)hxLQdkg;dWJ(vQ#TwEHYYGy-c^TiEq6l?<- z7oXMX6SL(VHJ4OLL{@NG^CB~fVtwcW z&jin+!fEuL`xWNExA8RJMsD7?VYSSeyZLLH)L*aiFXp9dy|)Jj2E<9dodl0bMZ1ga z`+j)mevJN8C_yGsFT8Zg!9A}u2uAN7g7OC3!%?PxA++CNP=ahOmp3Wh+ECQoi@Jdi z>Zq*jCgSA*aOg{(^@CMs?ZXGA>0@SX4SLy+e%$}V@Au)JAAgI)r;(4%wU|BEUj+k= zt5RxH%PjJf%aei_@GPd`FSJ@YQcG+TW2q#mw$2nQ+NH>H{8m=w-E0+i=^P@Buq#;N zP(3FAOpgg5J~suxi#K`?x#AY@<-_GkD8t2~cvDo&?KKZ$a*+*J?MX7t7JMp~gA@_{ zvLPaGs~;^e-gI#&Tf;MY?o&aXyE<2tBM2PWp2Gu7uHndBCObEKkhpn)Z!68jEZar{ z*6;S-by=B)5*~?>Ht)k6drp>*v|}W{n)cJjGWW-xUf@}HX6>qH`G$^(Hovj_<}~#Y z$bO``Ac|=j=TQ+%U=MR0n;pmn7sa87OS#vkXKB8Rq8xr7y8c7ysTq-YDlPr5DQk5t zZZhD_M%Kz^UnDvDfLL-X4KOJD8lTc3oSke)t2Q>WuUR{YIGZV6$}zB@CfBO6DS>f9 zcMRCy_sep|?XE6M;+*X54d(aB65@H(nU3I5OYKmCH*$upk) z^|M5#5Edytyo$r~Mt(_2&vxLE?~IBcs538(X619@yqBtLOuOfd3M+Nkea86ahZ1kx zMGn`wyrb#cIR=|I7Jr-AAv-9sbHp}C6}%xzgW&ePV`K%l*2wg$W0K^7s`pF{rfQvd z^+g5M2i&2EAK@2B>!W|BCKWQ|jenWp(CpHHYM8!LM)Ri(Z2W2_28t1?=(({iSg^MV z9Wa~Y)dk|mlp694bJJpT98RM!%KY?@K~eT%&x5hK4+E`nxXt7uMLLD$6=C_w&c}ls zh&%x0TYmj#|0Rh&>;;4Bxnw~JeSGla!IMvTeCZN_o( z_NZ#NO|H7mQ>6qk6tYm08q;yrGZf!fI$T+E$2pM1x5Z8Vu9C~%5h~e!=zBhj1X-Sn zDKR7UIueS6Yid}DHQ-F9&6QOt>mWuDwZX6ELsaT+P+FRP$O8n9cYCQ(kI=)?{ zhV0iH*L_`UZ7?k;*lL?63*)tzP@*N?VJk8*?SlEg0%1f+b&bWpV4ATf&VIm>WEPaYzwX0(Yk;<$_)@ zs}fz*y6QW}i{~g<}eg<`-9pFFq+PBo>DKSnaB(NW9wn}KMmd8`ELw@bt zbpDMWj1QN<;KThVtq`{I#Bm*tXI>g|@>1=CaV(*~p;+07R{p*3rm4>+ zxLiC+2c1K;>T2snByv%7N-sxjjQYlDt=fEeMG?CUz#036Joqzum1!`$)4g$cqTTm& z`&e4{B&HlwL7J)gI;PqhYPlO9icYwhlGY3tUNLjdM-l0>Vx zSGz;Fp;i`RH1xFTvev_16-Vz}(fDk5BIt+)idCV@DbBF{6;3+2g!Jlr|24hzpP?28 zjzC6C^1~=%NwugFaMEso;m|}$Qghb1#{|RoG`4yT`VHYPGvnmIO$4KAPs*b1p-wE9 zhQZUmzMNkIFB1j29e_ulDNiASqF{21{uP-K{;iufvC8_t>=+KupfbUKG zQnKnTOY~U%5w)=Y>`ztKonKr$QcpgVaM)S)KU1Y{TO;Y+q@E2dkT?)F8EL^5HvWbJ zC^I*I*P_8?_Mv(Sco!G}kHvo_0$`9iX6OBRrJlBS6-CS*pB1;eFd=w35m7mIH^~gn znmq~FJ&VsZ?d`7K!!@wEDjUlS?^a)VjdMoXFbhOGg$2ZhY19d%(+Gc$H29Q87ZK?Oil1T&$id8{j8K z3*7%DT>AUt>Z&>CJ{qPsDHOSRY>SVrplEj=0}pR;7D4fc*RRDxh=V|WH~YAN=mi)b z>NdB;z4z*+JEZ9eKjZhxKv(s#LW5K3*CYFLh@dN~E3>%=f5qg>)xQYCY+Nveg2W1> zM^Nz3KPA^CrBeP=ifCe%KK|+X>7eY~WQW?uQy#@#Cd%H&J zd))idSV=+0RG+8Twboz7ume_TRnh;=GS*j3uNX;Xs^j2?4P$mj9OE3>8|$#-dQ1>L zfzf-HNz!Owa@9@GASZxF!4Z2A^_7;E?z`M<4yW$B3=!24zSNFSUHZ*xX3RJ?tc=@C zS|K&8Go7BEZvC%rzT+@isXEe5fHK#a-en(duc!}Bf8g)X%IlJ6F)LfC8E@$!QGuY$ zcrRX_Ux)`Z+^598u57p5_?>v)(aQQc%yJTAf9!|U86$Un)4Uy5z?^$s1jU;pKN8Sg z>gE6ZOe1uvP?--hVv@X$VW{#Q)M_942IQ}%8asN^rhy&q1LsHMd-CrmC(o8(>>*Y{+W zv>@TSXT6egt}us8bMpln)R~Nz`Zlgo|A3SJuToh+sVWy?;;BJ{nFrvm27k^jn_hhipH&UrM6s-~yn z8HANz!*>Lfub&@v2?2L|c|c$V^Yr`7L<#v&EoasQKFhB$t^!M%c`A{I0fwA>!7%0C z&H*#HNt1vu+L`7S878H*&kKYZpm>Vv5x0Z51xV1PXJlaXbd_`?=W!(@=cVtJtiR-% zRLvx!6A&GM1DQKu>~8__z~g)eT1T%i?!k3KBi~NmVqA}H_W8cGaHU{to{;=OVWRU! ztDdUr;u}l*B`C88amwC}ZatVD7L9w0Ixpe3=T1^-aiq1E`@^0nSO||*HvAwhUoOm9{)^HMU0obn}-z&Lo7%(5m=eBb>RxfefX zRY;&nOw_QwKVm4j4JY7(j9GLL?*{fGl<{^_Ht_oE2~#whb{HnV)M>+LhpZz82& z--YLyFw|3j@=2<>Tn4{PdYr0K)1jw1e3!tA42~rlKK>X98<%L(6HwO<%-A0qfvW*| zpObichU%|z_)whEU?m*aSzP+A=c9rS0$AR;R&VpI>HvRv!oK|JMD{M|Z1LDzlrDHu5p z^ck4E{KLl7(o?f}y}DBg+r>tF{{{N=K=a^>u(61V8fl^AqS#|{%YL_pO2GAXCHg16 zymW7ObxhlJrh&eAOeE9Qn4nrUaE_zL&D#Eaqhs#bD|H(9RpT$cp#9!dk?isP&Ed3? zpC;joF6S_MNBvKm8_@aZkLCI-Fb&Nh^D}T_{p5V88#PXTa z0uKZ-wdP;=FwH;Aa&KH_iJM%pc}xGPFWv3bQ0Sti!qIP-brnOyqp-MFMFl76!pt&| zJ&7FX={3Q}Te@5j4}v&AyZ zRDT%=E9?sYIv6}hK|l5o&KLs~6^{|DgTs>xQegh69Y%m*^WO_A?~(GvR9*KE;8o^H z5bqIk($)9vM&s9c+TJT%bg^%X zt76X&8ks;oqQzciKBB(=Pi4H@;U!A6+02rV+6G-nHvAHjq9UW-Ml$a=4bQ-dDqK6#F?)C#`>M&5Vx{9@~o?>@TSg7+daq>G%dLJEMz?A$&jMrxhG08SrW| ze#YM($&YbY7Ts&SK2s0VySi(s^*9I3JsaCPf8HxXpD1$G?@o(~aVGFaSGxp13OLw9 zVCAC}@GiZ+rv?)ptUNO@5COi9*Ad(hTYY~)BViX^2Osa9C zVv-=Z>IkiL9}@2#fCmHI8jMk2AX8e=bYBS}%#S|yO-R|`#=}%GOL&7QyJl=sL0S$2 zxsOKghLnxw8uP$OD~mnrn;B~=LdmiL{3n1ji1Zlk1H$nK23oExVD14N{@6I8Qnwv6 zc(E|FHo-T`_|!A*Vg8e_9APe$%c8aj^jo+ZHIrPv<{IJyYRK!T8yTQGF?T?|-B>6A za@m!AL_79CcLa&iqdWJy#MGc(M%|6aT8Ygp{T;x%5N80XPf>X9t6|5OFEmNr?}2C{ z1Q;jJ|HZAK+$|she$I*=?D@*0*n+XT_h*Fy-gnn*?j#Y`;(Ba{Tej{U9YqM`dkE_^ zF3sPDg2lG&g;R?TZ$MB0kZn*Y{H#Xcaane}Sx-Spq5Po{*Ch8SabNXrOTYWBSgkz< zVNBs0s`r;0R@z)4vz01QzN~6`jKo>)y;Tg{VW7YYg8CK-tOv5lB~inZKXG{n@WjrG z`bzJ+T|M99)n1T9PBV2Rh)TID^=8o^HNnKgbif>Er6Yd0mKVJ|y(ZUeX(HWB1E%p2 zZmaYKAG?{G28AJ@$R2!cSM~8{brpzP+pqH7-O@95LV+)n@D2z2EoeoOKIJ6p@y9)R zoh*cQU!KvU_mAwC`{P%N=syA7+YukLia^6)DPer3*#Q164-XGv-|^`$fd|lMV5!YL z_w_jM%@?P(w5ZZZ>yr+r-MCp{-XT*1(o((>jJfAnapHS7kKPV2277yD74i!Ok6#E{ z=?M};j{aoK^f`aCI4Hj_Dl)%0QEStH&KYb!q{IsAwqOo3__-sJ=le|9C)R&WThxM$ zN*GF{S6wGsN+99rgVy~2Y!_rvXXdS-$xpowuPcyf0Ihq}bh7M;HmJ1Z?)Gt)2;7UQ z!%AL$Ox3GTQ@FmjA+P0=(rHXkYN_Di<13%=UAjCVK$`e>cnk247kW(y)%JwcL6aHB zY427$|8!`d%T(`P+gi*~!?#|{Y{pNr+4n|E^lY3zc*Q4w3Qhk34pJrfxFm?%^hz*X zO9kk`z$qZm+0t^o8vaJN-NV`0*#sv5cg%Jw}$fZ1|F1YOb*2h{9#6MQZ za&d+3_zK-U9u;^{qZR95eEp+2DtFbWwPzV`o?sTOLu_Z@&v;wUQ;l3s zz%Lan;f^h#45xMW`voNsFXI1dSRjH_oc4GqAf3qvI0siJ8!z>|j>j|aomyd0Yi5Oi z+h)|ugj5Brye1_GYV^*%eO+8s^L=6-c~~G(i3;Eml3wL&iC+tYH&uCL>FgN+B9Y1iPC}I>yx7`Ro(rN|e*c?~jo*+?3Trup2p zI>?NWVnJz7?{~bna7h1yrGQK>zd%?|vlQwADNlZIX~7MVAFqSig!|Q9K`kS$^^$Pv zb)QJF_21Xtw@o41vZq$;0%D);|KAUyM}ypLz~#XO-&oc%r}TP=L0%^x@w-?Ddum@f z#O2o%^!7`p+JUY+B1aqY)0_w3a6(E1!O@C*Yj3p+{xLQ?V0dh z>(ow3m<|K>P6f`_Kc*F(yDc4u3@|+*|L-(zK*v5l`qU)O*PSUJYT^9Stm6Cfv`F+0 zeiJ~{8zJ{oANQLu+AH|JqNB_RJ2u;Cb@uat+SdOxJp^L;oD1Q(V*VyaYGm5rwD~ow zY|q;^&_h=hC1OoI=u@ykjIuk$AlIe$(xo>HdY5~6LxA*o;R(UkBT*jG1&+X-9ntC(F5Rvm+gWPB5xUd*uT8G`{+^E;pVy^a-P}%067)Qe`=0*+|qu z4159hf6+u2x<1;Ig?f=`=krcL><5Ua!=1tq;t%__mX_7F`-)xlAExM|hZ&E_d~oeZ z!8T*=n0xJgSw4X&-G*p5ORm(?1mG6LT}a3 zG5LR3y2_|Fo2DJyi+iECOOfL4?(XhRaWBQ)9g4fVyF+mc1Sl@W-M{qxp81uNbM8&< z-PyTjXJ_U*r|t(z<|U2(owR{{=l*9`|KC>t7qP&kb;cDyl05%IfbASe6EHWf?|tr6 zvzDP=#=B#$x}YXvw#t$u@c<+1cAnFY;FtRM)>L#cN=TgfYt0FiwWl;_P-BmB;bt;|sx6DE}{>Cja_2&N8mIieScZ_Agvd-I7!&k_s=+g&B-_Nk z(9_^9n+!wv3IO{N;A|fDzhD2Sd;f;M90LES6Y9)r=ViJ&$`>$6%Bvat_jkQzh($y7 z>+W~G#Ftmm_u2O}vCFT10FZ9^mJJXQIHkgAn`ie&~g7U<5wE-04wn?e@aj&KEr73PwxtRfMa0=oZWO# z2mAQnNu=biULfoYI6(MMuN}QSOLWa2wyqBQARM<;`8lUD{(tm9AK1OXKyrRf#m5sf zoUZu?%?&^Gi-f&Sxh2bxFUOyahTY9F1*ebUi+c^BALTp`qlY~ME7VAo6MiYkfqj`i z)Bemh5Rr7n>tz;Tra#H^tx}$PsTZo-u~lWX@N*C>%ZS@g#_D2 zC;{0Eh4bE>QS;Cqxfo4pl>_+Ow!G{x|48xpiaAh!bzXM4|k+VT^EqYUJpOocAMu1tpn%< zJXdpSyHp-#(L(=!rvY*~z>s-~1+qdv>v(K9`80hBP|F8Q`$4Yqubywb3+Lw4(tV0A zE#eCztTbi9jqeAz({6vvcRdROvA_=kUT6p<)%YV$njbG{RN63}BuWW$MtANVnAu+}O%w#iiHyu?inA77qn?=uFy!Z(09dcV6TcpE z24O`s?JyZ(wxryY2k-T!&GEa?x#P@`HVwnJvFF_vhk0-L;n;I`L7!{Foy2ONQ7Oe_ z5qW8&Nti&lgW8w3ot_ikeZjqLIEDDW->G)MPeg;b^-Zd(R*+|r*Tj@dS5D{Oe6 zOm`zwR}g$V|37j1w=K8pwHsHfKK6?|n;Tjxl_$%j)&X}Z^B>O5?~H51JMVMXs>@_! z3#vg7vdQf)Kf$QT*H;s9@JICYvHFpTb9zg~rd7(;pa#&E034C$B~XW@q+BORSki6k zl;x^9RM~pobty7jOKfs~snv9_-YTat0};<}5Xq!&OzaUAIiLTj(XRQ3o#_SsA^Y&h z9YdI?CR~_aX`A!fERNE$`wxl$p1MNFfVR1X>rVn-yYQ+q?ox)*WCYwJEK>rkm@td{ zhY|VAq#PFdD?_-!c4*;G6Q`9=TFVQx8_DlCLoY}s97uqN zSwEJoZyJMJt8NjADgOkMraiE&S5sF(o5}UPK`c_Dm{bL0D@YjMXcRc3 z%h}_sq$&0!hLvh)yMTm-nd>(?sb2Mpab4z%n2jo!CH>$^{sSN#_JelQ)ycQkWy3riENj)3dl-XLBmttoV)2(CG%UAdNEeyo`?2 z<7IdS+`u{#&;2EJtxoJELlXzn33N80M*N>Eh z+Kp&8&%Ki+6sT1b5623-nibEtiMpfa(+BG?RXz{gZ=9r3%F#-J17 zCX~6%aH=ml{&Ebch9A1?s-SNuHLp{duh$BZmiuoLVNkOc|Q zC;Z&-z6iIPjr{CE_=Ef0tzDh^o~3S|AjSm#VT$lfv7SP0SKrO?=gVUAme<2@6f)29 zcN8p1u08VBQ1;fiY~Q%#m-v?|Ae`y+EhUeo&b5nGuYkj>xw2{fT>6|(cS+$tPaZ6R za3K><{{N_b5cv?Spqq_a_jePkS_2x}dMEju&;i5k-tNV;z59K^$ycOF8&n>}M=!(4 zVx0yW>fqi-8}O}4t8rs9?xW3PnqR(he`9w4#gXArFEw#KF)>{B)(W#VzNgJufUYdB zv7Xe&m>>CjS-!kQ`$l=UO?zps8QcaG$2BZyM7@bo7gXev#onC`v*pz1gs@ZgjR1Gk zACm#;FYHL6rGE_TOo5qTHT}RZ3zaTgLKAaD`$SHWKPTE-;Nl5Z<7S3eRv8L^%tS-^wkDO=SJbGD%BhBueH9<$q%*pk07V*OdU zo8$yv!=cY!Gs6A5y&vC{z1f57smvK-T01}M|K1P`KRAJqBYtpd2_EFZN)0DXhif1h zW@d`wen18^SC-)DOTvIyDl`eRVqSGbv71wtN;uAMDF>)P@wNfHGakaoH?fs6w`#tO zl-eixdIpHSR95Axp$3U6iMvS$cdul+n#>Y?WN~Mbpk?m%^+uIp=!v++ZWeoK=k)=U zVZw(SDcZ3+dHwPTEc7dxg3|oISo#*XV#;Wj;n1$YeFEDew=qvtEo`Fe>!bZtj?ep% z2b@ibR^m%D6Q9WDZCx6%H%6K~Bxxx)fLs2Z1|1WrRAtoDJ!1C?Yv+_aG%!nM`~qY)+O1 z0;A|4fZc~Nw`=--0jH#eK-XgbZbG;4=-6?zQw`c-d#w}&h1{I$3Fu4l-k{J@`KAnS z3cV-Xm0VK9?A1ofxC;m58hRKToLbrDfZgWEclUtRHjjy>LO;E4ory1YQgrRg-4ghP z-Ep>4H7k6wQG%m;|GC zGjHbz$gNtwdPk{o1F4{LOn zo^vE`uDQRjS-3Mv1A5{XZ2xC!0DN+R1pe0#xUH+=*i#WlQSJ`KOX2Pj49%ITFMkRr zQPfrgZLu_{vfIle)iuicshZa?0G^UgNH+$NA+wALOR4W3Io+DM)rhH&{Y#0_-~Sb-fR9S(LTJ0cdxDiF-WR88Y#IDd{j1;` zRc>m@1S6GnMC0TZhQN(Mhit9jbR-RoS&#tqe-3I@Rci-QVoR4kAM2je6*A)>n5;W- zO#9A3b4A98G1V#uZ>sUV;Rv=TP)K1}TO|{S_1f26qNLoU1eLgZ4jzalNp^C==8ssH zjiC)oG%L%ttQRRS&-Pr{KLCeg3;o~-OFHMk#o{$lht})M>L+ni8Mrf}F*fYcbJpUF z@WT;=^jjqROhWRy7lhml|G|0RAoTT6-X6a=d6iytr>%s+)zZ*w&FPpdLi1*qOh%ZX zM{!-@9qkzse6mXXE3XW!`m1!)R}cHMOC!J$4v<--Xk>0oq{Y!smvv8=v{kp?AXv6j z5*yR@@wCj=eIc8>$p`mjYqP!Ox4^K<-#I@w*A7Q9O4X?>PGXs~ExnB;?{-q1hA&!Q zei>j1*nGGtzGvnYmz4A@Q5=TXz=nQB{O zBW8X?BLxL3-V4~d7Rn2yMSq}ztp7jI0Jy}1n0OrDkldI^iQ2Nd($cK;LcKP7Hb3i8 z11kSrAP6z$RBo_W{fhw^W2f^#-GB^PZU-<@pFY#2>UE*DvavX2k|`8qzdbKSan#kt z@88F0SWwff$rc~KOph|-WR&)8^Q!?F4@tGqV{goW()$bi$1>^p$6ObBBBItM1zYnt zcW9Pl+!N4qOQd5b?#G?8r2KUswr#E?^OWr5>sPZD^{=d3b*GlZRH~j$=*9a3mZGEb zAs_t3LzkkWy=;|v^$1ioT z3E6?RlPg-F_2yDNbmrw8*?dz2y%nb)i+3p>YRG}bw4T-%C0Ej94(0-s06yb3hGmoG zV@7CFVDiPFS&~KupmxI|fzf^=kOS0GMlM#LQu$or-gD~e<8?^K(lrMo`O)QO=!>LJ zetoM*Ky5^iO+diQWGe@8cv?}Vb(MFtu~@k-HF(%t82#e@!pzen@dpk6r{Ug^z8h5w z_D*7-cyqyUY?X3Sn}lcSRkjw2STn?^qh6K?;_V_qq!4{29MJ0vmXBRq_gX>Fe|rpE zqD&I?`Qg-hu=%K{ol__)a0lBVIZm-YzIIPh?Q7tVDqew(DZl9Dmq@v&??D8#9)Qd9 zKJ~l$w?Ni6jot=dpm+WqZ|;-wTxYlCVsS_LT8x2bw|Im+PwIHDGK1#5x5E_{{)y^I zm3Vg@|Mwy9O4o3VRM2&}L}9x*4%SgiZ9pi&Unh#cm^ryT>YOk=`p)EW1EkKMQd$ie zmj>=ym~5`cFoLAusBD6slkTt@J2BPiF}rDPUCye9o7QW^=?tP~qH`?UN=sK=H8JK; z#MS~j!gN(p|KxW00SFWp=k`s3|Gg_8{x6d4`VErp5~a0_Z?&=2-YLzsQ)!3$2IP5) z#jEQRfV5kyDl^`dgGYq&b9D6$FFptiXZD*c1Z_sesc}c_t zoMi8Hc9l@ri8sNsU<_fM#Mw{2+?xA?W!Lmf;CZ5Q1yjp5G*;5x4;l z;gU=o!KP@ip~GsQge4yKZ}x&&ET^55Jf`AvjYIK%(mPQ??CltPTQU4AK4eZv@fglx z(Bj@WsHxrJMX9}>sg=C(kb#=thT5IObUnK{W#drzydQgB87Acn7;=P&}~R+Duw!w^c7+VSPLCREbUFnp{`7D4K!Zz!WCs% zlg#AMOvcz(c7V%O=d?w+v>}ZNqtty}X7pZvC~p9RYHv>jZuwa_^8P2z2{ey#q4)O6 z8sZc~@luM@ZyQtJc>${c1~2b(*Ho!xlr)}Yq%ljVf-DkaTy=T$aOXi|Y1Bf<`U`whac zE8GTk8fY0_YMI1_I~I8{LR^bf^4EVSj0fes#n-dPpY3|nIJ+g-nGvQ&4JEXh7vN?u ztG60C{Wl4lFeJ#ALJkm4T9@np;BQkx1I01rK zlP)hU8i1G?c#RxGy@l~cuWplT1J9TYP{FWBRn+^g{L3q~^$d-&oM6sf!#sgTuEb;8abNSAPxm)5D;=9aWLhKsEcz~k~5Nf@JW9k~*y zDikLK!JfAW~4*Ul`8M;W^K+$n3`XN zsWp!ubA^f>!vuI1wJ8f#>N_>Itzk;gKs1#RwH(pg-jsu4$Wf?5DOA+CG+ovbBi$}4 zBSmQ{a^%W|DM)u@#LB-rayI66?RjHI*6phDN-%;!j>P{>G;*RnIJJuhJA?`oE^44;s`%W-09k9o zIDKi|+$VDm(D*N~cm4?rdPA2SN;1=%Mf2PSa$USk9#7qNljdWI2k~-#Rb!-+dIMf0 zUh}{K26b`sucLYy_?p_Cdb^|}QPR3+@(4FAnaNb)hq-FR)3s=E;PTjn$0=0$<^GK` zuStec&Cy>SYDym=UVzxAN*k%VjNMd7cUrZSMme!vt_F0J3_3WkTdBXpz^<{tuNPtl z4ap(Ou{RD~Kg0076ra4U&-u~H>BM)qu~t_rzQRg&E!EnU3GwUG!3cqv1-{_ZCM=OQ z4G2oYjH}rrPKy%JahchE8x!NzJG9LD&Mcp9or~qzTy1v}6s=6VMX|q3vMx+{JSj3U6`5IpHx5m(-*!}rH@GC0eFaE|K!FqM-$9RQ{1 zhh{f6CkYEWAJK?0jTxB66za8bn44uO?Sou#8FGkfmHmpaq1sQWVGA@6-ze*tV{X0ih6Jl-SpUvWRa3{jTLvZjAACh4P@rq<#!X@ z_nXgV2r2&X{!oG(Q-EOPcHkutKP<2ETAGk?lmu}Xds{T_G9H&VT<>#hk@{TAAnKiw zi^ELh>d?+8{o1W1rnMN9j-R8;TJK=iO7nWD4vA(N`xCVL#{s^-<7Gm3!7WEU)iEty z9K|7zr}+4SDsi0#65l(GFNWMp)l7ALIX3iuBx4nBBu0p%W{gg|9h5{i1ZocIhAxLQ zKg8EqjRc`5FA1x$EYz`rTV5hk^xE0OWjsbMLO1p!T-z`JyY*hGA;1X-8G1DzzQ!e5 z=U2#%tD52p3P-nqZRH33DBE2LN2dkz`-za}7y;+QFo(}O5(yEVd9P;PoL8?DG063DjK-FxDyQLAnXGk&okLdhux$cykU8s4ZiwVu`)rs@ggW zqZpO2@(d)OG*#~+NA2E{r-I3-h6rqJM{O7BKjNxPoJyuX(iy4eCm!^EzDvxKi-!{j zjYV~5zZiS*y%xv#%RUE~OP!t+x0$0=3<(p9NJP_8neA&%!PBd(8lc-&ta`JrKmu7; z99Y6^K0gq(q+#+ywcwkp^(`AKG1OBlDvo?qmpcag);nX-^I8pZoCJN(DKOuyOoWUy z|MfTdhlb^F2k93=y@Xsu3KP>B`nK%&wQwQ?5M7pmu}{F$Ws)>(x$bf~DL5ZJm)F*} zfRpBW#zko7I2F@GkcQ;BugOLR1r7_~DTB02$Y^OdSJX+Y=LPA&B=th$Fk!RX7De46 zVE3!6BL!pKgOv6>2#y=}7t;661ITlGrb8<7iZq>i-4@k`{YR8>^mozy)q0nPJAooD zVWk>h{m5|@$^ab3kww9hYcE!y&i*;7v zO(KPYHl$&TZ!Iid@I@p{hcawyl4Jao!-l&19$wywpIc+7;)X44YZK1wL7PJo>0^_S zN{k23`0;7KXK+pY;=BfoSLpP#jP^gRGncpOIG+ds2Qa{{1tCJ=vDs zi>mK@y4mq3Jv0ItG9dTFxBhDUPO$c)m%-7uS5?%5WYf)q;(7CpYDGCn%=WLQUgt! zx&up%Udw>HGTH?(4^|QZ5CgrD!oz;XSEN z187Ulm2v5wvuRNL9>S$(qPA(&($su>sr=sDaHzgnr<~|nXuSvD&+a{_x2Vo+Jr($b zoS~{ADnc>r01DL%EiYc9g^6uQ#Y^eOqrFxLwN5$wOSe>Z(BO=ev1Px|r~clS)#`9& zpj|h%)S}`Y5X04l%+(&lFbOz2bI)6sDiS#HD{52fvm#^E!$Hn7Izry2r|U(td(i%aiB*5iZ@bb(txrw7-R?Dccdfcxxfd?A;XeRM zAE*_A$!Zd6EEhF$gmgnORbnY!N09(o2YJeuPQ9Ori|)J~Ql9qCpO68l0ZTab_c1H^ z%GfA0KdJiWfHPF`Z7DL58)^ew*EBLRxtKoEb+0wX9cHWhhmj?k?q_<%#TGuStsqJ> zN*IPph~#_t4;hxM7S7t0VcvwoA2Ik^n%>%U`AmWnTM@s-I6mEgSiS#DFzsiX(}c(^ zPjSW4>6uM?S=Ef3yX@arYiPh#pwO0)C*TO7d)ZI>+R+q?4AZF*bXIDc!MSA~;+Cb! zhT7=C`1TmGUQ;Nlv|}uJ!#86->Zy|Ks zNX>abpidyt1+NwwVDlqi{*@wXpsq@7u~C{zn9*W?Z?uC@#i-jh&dQvShNjZy)(za5 zm)J%$9Grv%YUBNVct8Tb(%3--{f^`m+C31RD0 z4mflQ!}WD#3Tdp@2wI|J9qS2#?6ih6r|F0Y)ft6@?ta{2)X8|!nTG3wt3}*zQ;Z`x zj{jC%X{lsoiu-C{jd`zjyf$Z@VqsHv&{&AVsj&6|~EWrljQABc9aSuP`_w zGJ1`!ac46^syk|%KdG~zL_BBdFrle~Gw&~rN)uxg3C7>w10JG3CK><%7RTB1j8fhE zit9L;-=+grK6T=>L%(+ zrhc`<^NkLV{+uBli6JhXELA=vY^EHrax&R-Z28ReV*iZ&T;Nk(qajbHY!*RQZWe(t zOnaE_2kG>VgtXOe>>e1NJ@)x`xeDvRAknAKp8*!@EoY$NmSx=TwGwWAWJ8H1>fV#v|e=E_{iaU z&c7BC6vL3R8K_?WF+_pe+Q>>zWwM8}jvJG$;)J{y@)GWz;2aXmNkUnU3uaCBdi!O~ z6~1X8Uq9M4M#;oBb1+*lhw4BiQHNw1HWSrL^T_{RWE8fa;5 zOS}X@TmT)e+y0f2zF>(5LEZ{Gk9=U~-h4r}A9Eo2C(!A9$gNdR{O6c86mt39jNR1$ zW*#%CS&J9`C|Wwp8FgrjX30~v`MFFRGj}z$QK=8Y{sLld&s{^rx+T$if$>AOBkh~V zCHOHXX(}BgmR}JcWaPj0kPhZ8EE~IpXS8pM?v75U;4bLE4(ru8>+MI)1(@U%wwL1o zM;QvR33;kiuNA{3dO)N7t;1X(MS^)usZ}ekvh;ET_4b+X=)KVs)`J)u6KU;d1{sL&^YcvIZ}3hirc3;A&S;8W9WJmv+m zj*tep9lyLVJPz3ud$C0NNJ)NUmj)DH4aJmIxZm2Od_p*qOmO0_F63irxE;E$ktrX_ zR_Huh>MO~ZuumV>FL=#Oxv;(fRQWZX;G&5}?rbZM1WdDy^cB7dw5}5DUK{9zZ2gsm zd3RD``$~4#A#5lTj`%AJ773~+%K`bl4V@~HBhmIZbDr~!@FoPgyQ2-CzLh{|f5}^8 zQgKk%Fbih_p5~X{lgtv9K!INQN+f-UjuESsJj2Ij8Mu_b6+SN)xuhWLbig>sR_^M@ z6=Tc>B^u0j0SuilZUCY#M`ev5EUOt4f9jFtGz4o8^CI7$BxA=Xu!>ppY1C=1)bh6l zB>&w)c<$_ttcGj)8_=l-K`hP(6s7%k`@t~T!2^grg(!g)%7G|h>~o;_-%hxaO24>M zeCT*1{@iPL+bj9?@b-5H6~W(xjoV)DmueXkD)%7hTfxRw zG3MdV&GmZ^Y`%X;%V~th9odGscF9PHSOw;%h4vo^XGt=NB>M}#A4>0DDIRq!S37Pe zed28R`LeY@)2R>|c0oDf9nV2$Dd*979;i>;g^cL4y#%NV<@(!dx9Ap4ri2xIPg>YZ zmy0qjMsNbE(b5ZkY=@y?f+Exs&-9PcHN6R$2d|JVy&;S!X zzMR&K2=xZ~bprA{Y8|jrjM%Ut2agV0(#yic7K6upYzZwPBO=&LekmB)V9#a7TUTG+ z6I+aS6?#TyfHwjQGG<}z?a}LZ=O=mnc;SE>>h{irHuiW24Fz-fSCWjg@%EbUc&{Q4 zA9(AI!S8y=mjOF1fZh2$dI)|2h~wByu$ed-@%*y-e9XD-xb9OB9zV1C0^{qwGjBy` zi)%2O0(1M<04pWDz>S{>bq=+pb4wH-VOnvw=qs&=W=zGgOYC3mPjie9su%eoMn|Ec zTR0%~08BQ{q_WWJTDZr!qJ)tom+9QczB_a7k2-&x)Hl&Tn92Iw?#Zs`-HQ17xV3xd z7c%ptqO})h^lDoOJ69ehsPs(7l)c3(5tMX9h3Ty8@OT@!N~qs4P?6u4 zj_UEo65#|w4B(cPA_@93WdIA^Ua*&L-dJ-iBDv zfGs`ocr8tILSES{lTy6`((7TLio(uv|x z(3?yAfGR)hkx?oKPx?;%s;T3cx@@`5OJ3RtWAO1OIsb}Ze9HEhAf^K(+W7L@MIe}$ z8TE(`cEc|Key#+7Hp?XqXWE+OuZ0u*=~# zR1e<;@I#P4iV@xv!CT~1E_1uTX<>*|0^H0H<>}llc@E5d6z+*9v=KkcpGrrRLqH6F z&Qqw5A+$rH6XE9f?7{le=5c#=2bB~s6c*UoMBk0PyMrwU`9Xm4g;Jya&SIda`3E!c z(NtYYWQP6U#wJ3@t{*YAbxUq2`Mxdm@y!9XP5E9LCzeQtY#*;j7?xicsgHqKG6MIK z9gIJw?QV)Pe4%t_{UJ%y^tToVdc}YrxB#z}7+ZBhFhRYZ(HIBbu;9a8B9QAzNUfnillRy5%yo;9x?#)szf2TE3br zCbyd8cbKDZ<8v!G>FeA6xJNVLA0SjW8wgM}qL|0~qj-Csk1SR9NN>g!qPDjNH46Un^qs-ahI1;y zTtI%YcmA3SksIOoJoy+UC*4OsB#aEVH9%pTt1kW_9|or>&u0wx>cL3-D9Xl<*uVtF zOuWbS?|07xD(oSb2bf$2{(OYBKMH8B`803y+$@k$L24dfx$PM2*fEP3f0)H8>!Ah> zX{nXCh2meq);<_3#Vw}fGPwF3&;3cfg5CCCO9y6Mm4wQ38XUd=3=SJj`RF>xijL&J zdgr*Hi|FO=4B3|?NDypUkWsT73DV7O4L-!}zK@=n5HYt*KvvrvT;WO|sX&~>13EsG znq?hc&SwrjF=$gCG1q^v%jfRr*h6?(Quf)x!60OqZJ^DfjuihJ?%?vP2kIezq`Nrf z_5OFQfPiP9DK`mGMNuv_AxcHzdK?a3hf$9zad;YmpgEtHB8w$mNlC&;ga^kljr#qs zFny(9P3+SS*zQZAm6)bO;#0p1WWyFDgcy~g1*zSuuqu}jVe(w>B&({YU-xMgW$|M@d8K=3$1AeE)^8nQyY~G zF!vs*_t}#jQ0zEGyD|$5==O1XU(xuM_h2sNSY`ig?8E+1lNgGQVj73Y5qsbrjI*v~ zGmeG28r;7j`Z|8yjdYBV1D;iBIn1}a+vE?L^DQwth%;Q%U%dg!Vj{XX@s|OWFh2#e zuZ!LE{~8e+F+&S#+hPANSTBsE;eVi1L`B zzxkG3hbg)C#e_g;4a!o2K6vgU7k*|JsN9dEVW(-*;1T;R^F8}YqIlDf>*#I;xy|wX zksrvss-BB~!D{oVE(+IC#M0Hug7t3QxZsp_PtJEF+qU&*8xAxG97bTB=YJKJBCgj+ z><#ql_jFq0lX25@qxQl8*f+vQ`&Uc?gQB$f5E@Fl2{p~g;|9CQS6P^J@DRJuQ&~=x zfI6?MD5_1D_M9WxYqFQ8nx?gK7m$B(6I&+4KC9fXa@A(M#!zI?;H;?5+&%z&f z^!B*M?XpjC4ezEgtEhNqIdr)W`4%4g@4SS7Yd%}7)tMVNY@@d@cip}#di|6@s>wx| zzHiV{ROQHEcM#RZ@h|!aKjkxXcfl)v6ZJ9nI``GY*&p@qELVk_I?6$kd0z?sC>a(T z`Oipu{O!@~_(Yd^<36rdl4St)C5K*$O5emUQuSA{!qT#VFP)e#8WJE%zaPFk(?zGh z@nKXHZW7F3vPVpF&&BlvV&bQc7e*|N=L>Q|9)h$}_zicPfBQ)$wik-$OTgeyHn2OI zs{O|6AZQTWt&phw63Jh&JmBGrlZXC86`NFjYOd-l&NtR*PixhzCvxO-HX+)YkH8BM ztVEo{GN+tpL;z`y_wqg`g?A33#w3J_-S-=o;wtkY)%;!p7;I6^L&rbfamQ3aAjqfz z!lN({RuQB8V57~BovSL%b;VDat;3*$wZN9N*#lKMH1ORqxWa&*J>r&zX@4`QP+ z6V8Q25KmC~)3Ijb@09P~qyHJlICdQNUWxn?UDI5QXKVXlN+ zKTw3}Z+yIO%tKxA>z)T(CD-0QEXq`|&Rv|)vdFgkFKiPhS4XANlpdL0qV|73l_igX z>s8F$V>w{}QkG3}1wxn=l=-FA*TEgNE6h?lFvaEpaq(IcD$C$35zFR1rux)mv-L4LoLlbLKv>n)uuyYtf|hT8wr$+j~6EC38#>+y~icbMQ)0tJKh$OFkuaL7V~u(i=mM( zSBc=DTvUeE*06=0rx!NM=Z*asQ-xNKG7b?Hj8kt>KX_f!5&o9GS&k`+qQT0aUZiW=O2TqN zYY{7~vlU7Ec&ZKiPfC;@d`Yhkn>6C7`|ViTW8#PjWT;?WXzYqFnaZphZ-~d9N51(w zC7Kb|@7ymGDHq9rm61H3?1kC#^xGApEwGSfOBB6F;UFKGx}>; zcEV8AxBbO8%(=E!OW0?5fx>BsV}*1u1n{Ikj6Vi)f+@C&{eOpariaW^**CUI%E4^iH))zoEsWssxtHRJrUwT`4DjVh&pS<>ukubCVM+262E_agTc!uK1uU?;yq23j_ioq| z)!lv^IG77npryKTR5pfS$>KAJayvGN=ggeg8H^VoxQ&T$g|>=cQ%#D*qfwY;WWsEz z19UXMQ4A(riQ}t!yZyjyj_BB{Q#8e8 z0G$noR?mM^-qDh`pniKV?KC8?-Z=e=<*B&$kfw{p$!XQu{)M2!W~KO~aD(O+AN$um zx^kLry>iOsL&kS%>0RD9^#Xn;gj2!&Xz@X6Ob3wdU(H<48IyMVi%bmcADZkjq=Eu# z;5!?`LtJgmpN`D{h_!933zp@6hS-bJ&}!l7X!__eKXnZ9yTHyMVPJ7aSy=hEW>Op}*s+<4xu0-Mh0~T@7^ABmjM*xBAI-1?v~-^G8F1_?V`Az16ii z`Hc)tGeef$8kU=ensz(#Fss=l57@e7Dsg(C(rQ(IaOhwO4;N@xfkcjkPsAwb8}3G~ z^(Lt3Z|vg7>#Sh4+2R|J&1sju+De#nFf}Nnhl=A_7$+|ccF~>Nyqe*2Lwru6xYpYb zB+x{#0t!Gp7ySth_XbVZcU>K1YrfF>i3t7Z8KV!Grnh=}xog*b z-gpJ>iCooTs>;w>^nLSi*Bse{nU3-(1v z@*KxSoyXWIRBYzNT|x7&h9$(6zaqIjejXWTBGy^+8ojf=9Dz$Jh$@+AXly()Er=E;o|c{>(daPI$>L&e zWzo=RsVvb|)9oCcLoWPU1@rd>@h$UMjTh7MI6jjoi1QAMUkTaO;Z%Kh%6CQ5#uK7h z0zED{Ou~J!384Tz;on| zwybp4vd4 zZrFWH)Fe=XN^B**E?E0Ruqo z%FKbd3J9cRPb!(NqvE8($_)>zWCR9X=SDs2gA4={Q&e80%fdSwJBax zH6V&a9J7h)&m-VBi$?vcCJ3{bD~8@tnooCy9l0%-IVx-jby_7XMq zBgmBfWrX#*uxX#uwP)U-OTzl9)T_{fU)Vmyf`T=F#wp{yjn>*h$DCsEi1=1tk)9H2 zm29!2iodvdj!re~u^KEEDM%$pIO_5HA<*7|ap>anb1P7QC^_JLDGg$(c0d=Yp=!U3 z_EVOLMv7!u@ER*GU8Ol`Omd|XgNOmAwt5)P-YDN|=X*E)_B(?Pl&2Q=S-C-h7Y;(u zZRo8(6`8gMT)Aiqyo-|gAQ_>QfeiOlq;h+9>XU@BLe$rZ3hAEAJ^5Ttw0rbx==+pF z-#6Rb!+6+<8@DAsGcR||S>}~E@ksy(r#}KaYorm``i|uN?Lu(c{z)tVSaasFpIw?T zCup9gs3{ukC5p?Up@7kNM_P6}0nK8+WfY}6;q;x?AnJ99RvwJ73T)9+LbnyTmaZ7s zbVma;#rFG0TgPt<)7^8ONa ztkz%%{C!P}>`rgNs8;b!MX+*7h92&*G9$aJp%(!KBG)^|!!OQc!gov$HBhLx_VcB- zkr6?sv7EOTs`dqq&6bT^)-=H#;`=k(*ujWTpQ`>;zI11inb=vo@jw>nhFld$b`gqO zJBhLFmWGVA%pE0@f%wy_uTa9=M%+z*uqdx z?e@Vr_IC&*Zg3=#K{D&Wn;lnwF?7hTpZ!Wyu#a3>;FP_U3X15lj4F~uJSx+`gH-0% z{REt~anV(JAgE{0A{R81jHrYgB*YU*Qz~7r$USj{&*~@VyUr@+=1PY0hXAc;#r5HV z)!Cum*Ul(e)J@C-ioxesm=Nr=J;4&vWmFJ?%V3Z*37{~;%}8s1E1R+BiM8_!A@pX< zTN;NZ%*cR{vfm)|DQQfykG0RM>))apYxbYHlWx8C@z^$*%0D}FCUH2$Vc>H9z#Ft#WE^Tog!+At zi$1}2!UnOfi=)KRL7@1zD6RvlHoZqnwXZE z(Va`^GbZ-!VUqc$*>tpRm3e;2;8?{y6%Mcuh>H96Fxxx)#``M(=2m^Jm$Y%q6CZH$ z;js=a0-x_NP%wV~e;i$NR3&a3yxF$7*>1Dj4O^QxZ?>(QZJV22n{C^hZCm%dzpsBg zr&FirKJUCU^UkObis2J;1%8+`b&shht7<8K(}O9C?R4g}sB{F)JF~+7euJ_cHD%P| zu5TZSwAKuAjN_j7&mtLJ%G;bs)&3b9X*zi&QVqSYFjD_3-|sKPh*PJ`kp~vx$9&r= zIBJl_>Nc)ITU3LfM-$qKfSlkzLSM*a4b8Vx(u?v((8G@!K59kc#h@8I>~=pppD03@ z4QlBjUWQ`fTCN)V=4K2&lY;Qn&tcc+vx3&^kL(-p&<{Z=`gPxezBlKDwDKsl*~Hbc zXaEXfcPKcdd61nN;YbgNkRsu(NjU(!CkfzjsuKIBE5ukbL6DoRG>HfQ3CW=5HZ4A9dhJdu4CX3qkxcyAzrwe@K)GCuE&m5O7|y$XJhsb?{y3$a(Hg*Pd70` z73Q7|8Wuo=SL0SvUnoX|7OnhiVq2_3!C8_pjiqn28}Z48PVKkGye%fJ?_ zyW1Poy@(j~0;Sp?aGT}66ia{H1^24DnjQ9w^rAc?0b0grBWcPabxp*(CP}GQ!)Ks6 zemK7b)o;{2!cLlfDRls}V!_Dh$85^m27snYYU<4T-epiotCkW34OI zwVR{N8IF04Rdmfm0ejVL1i5r8eukp|so)C|xg3!n6jcYfLH>{pDm$_5pwHCe* zM!p^V9@$8PV9Ba=gBiMe{r27N92F`p>HuJfrv{6xfpdPPi$lMo>?Zgp!J330OSR`Lmt=#07mBWS|YNa@qHlw<^H2 z^_3d#Y#v|ynG#E*yJ&-sIp&1?!ZKayuFyf6W0K4FOGAA(p8R=2V_!=2fkZ?Wcx6Ly zvSZ=X^$-Vt<}Yu-eKcEqvfaa6qLt;gS!B>uWY{a22rO>1MY*0iy2X>I=mFLJVgzFrACUldDJ8;Nc@ zlV<$30LY@GhpjMjOY_VDU<$ZnLejF5rP2NDp&wM(BbX>9V{7)lM#;&E+Ujq7II+bR zyJHfMy-)9&BNd%ttL7u;YRx>6dD_jL2;<<7U*)q3kg1B|hvGmyd~%MIbL-=pBdI^q zGqcAJU&Q!eh7Whe267sYnKzwXNeOjj&zd^No^!^T#0YH=%()9XTzslAOd~&a%aO33 z(o>QscI)z{&+DI?_}vfj6wNKs+?^U7@{EZ^6%-&sIF({oIRbuh-Ga?4Q*Gj#+X8k=sG;g2FecZx6%s1Jca*LppqTS&r7Y@`J%0u+~`XRBB(SD zAi7Pimruc(*sK8eKikaWl+rT5a$^(~JgZz7(~VC*)!VM5h69#pNkDo(%Z;Rua?R`g zz9Loh8@%oNG(}L$A)59BY2kZG@Tay35C{tL$R=4h5YxS6Zun3WMjF(Cm2pw#HdG5W z?UW(!6VaL8q~&(Pt#Dr8%3oRn#4}AFns6ps`?0TR?h|>iGoMXzSSL+NE8AeZ$BSdqW zi5_s+lA%zs`8mwQ)08AQkt=4#$GJ%QqxXFEsZhqEVPG@3(0Aw`+S?hvfET|!N|#;% z3%TxZLR}@z*uoky>L{*&#$ZHbBi0BuXMc+>WCM4vO+9wP&=RoBOy=v(pHAn9-&ve9 z>s%SQvrq8^mtK84kQj;|R;Bbup~OURDviYdei8+uOFANx$*CY+&p&t4W@CHyE3k)< z_9v5Y7lv28$Qy)t-cU3ulPGIYGLqOzNY>>WDbQ%_myhi4r8{v;PVw>^M1@x&-tj^6 z?(IfGLxC(A>m_$#PWCO8>y~O@;oc*B;l!ncT1-OW28DD@csNgoDxW&fO(#15o%X}R zJETs0r6T=HY*BQ%oc5IL(s9RZs+sq?d}^FoNGj=^cOWNv7ygIG(a%JS-T1V;eB~2E zD+u8e@9^|$3|n2UF-2i}!+99ih7r7gR^LB1$2PVk#VjLU@PnXI46H4J2@?AMP6-X@ zVJH^mU6Hp}hJu=IS22)+uE077|FtH=ba7veB&NJpJ6T}TxP zc0j~jZF-C>nE(v0BeDH|GKzx#`yA2l)sCMza6x`QK-HevS#Q_l4=B6D_?+%;=L8K? znnDsV=L9La2MRBF3&z=muBfn31C7#-OT?Awo7GO)m;M$-=#3RnfQ7c4$njc1ucoEN z8LV*M?Aj*(mx9q^i02}ODo#C^S@n==PYLkFGxH@cb?z&>t;g#Oh?FO!RpS{z?g=)} zXk_^&m8{|>{tbryimbf~pHo{vDQcgh&P!U9vlgq(W_Y&3 zlF-~_y*7}q0Pd=LmC^Jm@NIgGc}{(tJvtXwYbX;%BlyNv7WT%~AO)Cx)P>T&75ezc z7TpBFB*|&A{~nB2kqk7}?wvsBw=|t|vv?CoV4qtDse2uJO_qx;KFX0(38kFU&xF4v z0qDPMawaRU=-G+Mo?BW2I>uRC7wO*3qh&ht>f$u>hMbY{O@+K*_GX^*f+EytJ`Io% zEv!hSh1fc@|E8KIH0_8jAZOLk0GfWQE9na5wT%et8yS9m%e=7zHiD{tKu#3faC@#a6`R2cJ|HxsZ^4f$XJCFZldHhO zOJPv&zvh8CD-LF;eGk(5xFZjBUTb84RNeyOe{R0VwQfA5t(+eZ2FA2{4a&6>6@6p$ z&TJjy*d-cacM3uP4@ykBJ=5V)a%0n0yG5kBdQ^s|u)yWMVcYtU&%}h&Jd2{8zh5Rk zC|(P8nj%z`4>JQHUOy&>YuP?f@2PTTpV$&P%Bl9X7N0KYa=-vO4Z-s!dA|Sk$3etJ zzT|!5`MooZ&@)qVN%%#Sd2BC1@ApF=sm6hO`{FH*0E=s3D999(lY>5mrBESbJT2Ht zjJSL=mDtF?wxX*kO>i~*T!9x6PSVLuVXeNA5JD)1l4}{VLzN+n#L^z&Vn6(fXNoQ1 z_h5Mjmw=z+Z4JH8g^uijWOk;*QM2qSO)m%+XgX__pT*=MEvs?n@+JW_=!K6)yS}Qm zs$`~Y`1s3ONij2Z{;Q_H;wbi<9D*6;ONZUresza6k3Rps0Xvek3Kd7@;l1@!c_of? zI(o-2PT$x+r&kCh{^4QH9BBvfFAog?pc%UwJ!}VW@ZR4g)WSvjRLlsqT9Er)#D3h0 z%P4xLfOlnQh!rh5=-b_}_8Z}n-^PN_45&WEgjvR=O9MxsqE`?9O7&ppd-*RD-@bMcx$8hYMbbaQIXHJ6)NOb|P) zre<;e6(6}JwYi)jNEDt*A+uQed)BO~+Fu=(lKHaBA$z_cPg+W+4U|HHFasR+^Kse^wE9pZ*xAw7d+*7DO?Ji{ICAouniPj4(N$X4<{U4V# z_MfOh{#T{W7`-Osm9b?ZNt*78QkvasVo)Q$+S3Iwb3Y=?W}Cz!+W54o5`y2iQa~@` z<((*X{jwUUA-cJ|PGiY$l9Ey9%Pm^oJ4|3619n*TK}0sd7xOEG-TtY1G$J(hsELBd z)Z;3b)M4a^xR4ed#izD!C%zIfMeDwOoRu~xfM`e@Vwu2p_x9P$N;*E_ly`N_Jf2g! zQ{$TF`2CgnS*7FqOHc*_22#=OC)>x?b7*Fp)Pn9h7tRR>=MKhGje9yduGK9BI%6z? z3(^h2F!T6x(|Q=k`STc`{Cd9v5-CQT5fne>4(>z(*w?sBV=dpP`5nMqd=jdCR|ZyoK7ThQDD3a7d)z^WO2Jf9((tQ3hq0 z0JZzy!dn{0uW@_P=B<>ZdUot*Ahl_@Akael7cFt5s?(*QtCT6YGr==5{6|zIO{jQ$ zK1|fHC<3bTjL?LrTHgLx8+#Bu%$9ja4jk#oq5a@S2tUx<73*5syWZ{zk0dlNn>B%TyfMaHK3;D~iqnvm$@M zSj#C~>fs|-K?_uh@=X{}Vp_n>wzSr}KTmI+B!jYqL7 z!iqeJ)2co^+C=X{K6oG;+g?vvS1jkGZM;Zjbp7wZcj_CBVrXk!1}PGYKE=_!y0s|; zE!H-e$}m3$y%ukC`(+S1iu_%EtvSoc2T6Sq7~CH3wYN*g<4m81YnEs&&HUbJ`NuHD zlQ5R8I=MaJyO`ug@=*fG;i_RGS+FB-V)Tr4^5p6_9_IeWQh5TPlz&9Wj4MzHn<5Ms zK^$HQIzeX!(O!c<0&>E?@KW-GOUS`UI9I>Z^MSYfW%BZ}nzGg-2Mspx#=Ua-xSk1T zUPDP!mRq^bA_zJR{eD(Igwv^V)E#&tr`st&EIL zE6J;oH}}iLM#;4)k{(1rHzR{8BZ)X!Jxdq|33J4ij6)U6@ihUjlENN)2Wc*h2?HA7 zyW8T-x=n%bCT0Vidl)xR#RDK|=S`T3zsn=h7WLo-HV|4!kEa@JYf z1?QACiRY3XTZ)hMFZxs_i3|IW%bgLde%0G(N?*voO9AcHjDSi2(N0);ugYc@`uIO@ z7}C(8u{37AKQ@mBO*B*a8f#2NbgNm0CR`+$zVLw;8ASmmsqPrRNAm^u$R1&RcpSO9 z+v`c`@*>U?XL>){fJwBqK_eq=_Sv*DQf z!f5*OmYFn48ePMx&Q!yD$;3`VQ5<57TT~_`wM_BTdFdUT@XXnh)b^jDifaaRgVs3! z;)w=Tf5uXNTJ`3tOKm@2DKwOubXi_jMrgkrXL@!tkDN-C5+P_|^$}kGXc>0XKp$Bi z1WGNgmp1%cwWm9HRLWt@xbXDt(vgoWW)k;^dL`op?#Aw)- z^DK;$d_$tsH2rPxqFkw5QVlqr#Bg`qU9ot2e0=QpQ3HAy7WusC{%8id?)1S-vl>!p zox@gcaQRf6y>4$C`1$#Pi<#`~uA+H2`Me&PhWqt$)n$){p$lj{BrQW~=Vuhk%U|zu zLGP2iTh_L=;CyFaj&y5lYjb`G5G6H_DL_|A4)SwOb{gY^4d#X=5OaPO=LqL0AK*9Z zV(6#KXD|)>q5QnTqnB1vMhs@pn#13o8ta8Np2+;R*p~BJgWhmPFWZkD!MdB#1yb1L z%$$&pt+$oXzh6{rK4_Fg#fzMg&^~$cMC>l`1CenX1CIo+PnJA~29x{-ShQ5WeLtyT zf0|Wpo&5oTxFZ;Kn6IB%N62?yIVXm8jDhYLrFHDG1}7dlTvs+$eBAFqL(Ie-EhGXw z&V@@GOie+=s`(+xG#Hx}u^=lc^YeqN-%UyJ=e&9tL&&)P0ioX-wW5>#8yR7EuH0b_pYYANlc9` z)D{t%VHdIdOkgxyaPBx%2TiMCqMd*#+#LAMLwXP58t|)mDGc+o`3fK`gj`TnSgE`L*6as9 zco`yo3zDLRN_>8 zpt!5T!$Z)v_gSL(e@8gc$5E3>8czh!kv0FYr-~y#_9CZ&+MqDyF{kk7XGgylQ}h=a z?qxWhm`zRLayGpe<h!%%F|Z!Y20}FqKkfN|ht7CuQ=+XvAj6M>cKH zn&;B@`*;Ao=YsC4nm0Y)E}9ovdrJz$iD?!L78RX2{*kR!F>yE!aj(@WW}6kTJgW%~RFqPoyVURYwbRc=#4NBPhJf0K(hkz-_KaSxq2;=6n@DSMnn^nUF>qdfBOoRws1 z`oF{0`RX}#M;9neE#Dp?QH9dyV(Q@tAy=xB)K0X@LN=07g4X{0vh}2@?bod2iv?)5 zzV}oF$dT-x{tL;l3EC#$gGJH7qF_7jd}D9#%lO2EvhhL#;}kR;hS z{X60$B}Jyh(poFrwe2VtRTX{sy);XM ztaT&?d#|1k*^x^#XY$Z2wBj2^h=(q=0=x%&!V&mIEP!|!YAHfgAqVegDgX72Q`P7f zy!oz_ePGUv_87P+2owu?jz#oD4ej5t=S!EbXHxM`-LZ$CSB*vq;*)+2EC3;YG1Dq0 zGp5o(`9<#BUn`6asfF83hq!>_oO=HuZ3@S6L#%r|1*N%Ms`u@~8lk6-AnaY-8S&s4 zh!hMU`fMcbNuvy{KcodO^0p2PY<%oO4K%%E(!Q?zbifhP#su9THjAin&WPn7B`O0( z;9sLoGcT(!v@Eoc2z)d2WZ^?9E&r~cJAD*6D9&52!x9@4^Ldi{X~B`+aWh1ud@ojd zBi`Kbt7<{Z6TEa^AI=(9&o#PV7n@^0t-fCGk%6AURSe)i^pkhXn=^MBT#-=|A(}>p zwVAsD9e3$&AvhkG=q53LKKFDLFmgj426>}g0OsqiAxAK+hM$~;8a_w|x2u2l(kqXE zxwR*F5djRuD~k+|h>`-4E54ihwyrC|`*AegZgb$_dYNwXl1P1A3w~QojdS zg)Snb<8r=uPnB(xM7=m$U>l{O0pH>R6!O~;`snOfc?*9D1nkp&N|CR6v?)d|B!zHS zZ(-+S47*-RQ>gz=W@h9(zCA$|?OxxQs?Q}bqrDb0F!va+N5Ux; z#)3p{fAD;s1`9clO&=q=Gs#?AKItK*ccHDR*}EkWBdcv2nfhf*^SQ_=5srn?u7Z63 zz~C_MO3ID9ScMdQ*<3YWslXhgq+%X8N)}RPu^b6D3`H_8BT* z0Sb}+)}=_po)NfzifG@gnF*fS9*4c5Xup?KKdmbD)7x?oB%{U#DKsX$QC{cN0KD^G z!bPRRMKCa|W5C|RE7$p+c|mPO810+=dsXz2`xb6CXAp|NUTP%2(G%L>{QKbVv>EIG z9Nbi)q}Ccc(Jw$M4;MCRet!%nT^!_4Je4Z~LIYi+<$B+an&tZNfJZc2pkxtM7mbaS55IB6^;1l>WAOu*8esi-J(eoZMnCxLEki(%p$Zy2BwB|PU z7^+k>zZdW;}0mP*%F^$X*J1~^q@-;0bf6X{ePA<4Jc-8wk z&$$O0*xwNtQYNr-_MD2Jv6rxXy&(U>{%k96t2LF=Y_I}7mi60M{|T;Qa3W##N266* zLZ*J4Ea-lhLoCGqB5FOQMNf7MWT>9elzVrk<10ZqjDmHzlyA{sXSNg0v4Rpae&2r0 zl)v<4!QQA`Qcw!^=Ey4`HwX-MXZ+A!yLq04(x3HtnJ3BkK9*c`d3RjZy@l{ES#Q}G zFPWsP61PYS#f3Jfn`N6N`7)Y85+<)(&uw8q)DlunZ-oAH#7mNH1-+zJL! z2DSSFr0Ue6=Qu?9e77AKfo+gnj?2{aqu@ttM&PsbvAJ95>(`&Oo1?~%b3&>>V;c%a zD@6oKZC_UjLAY}6Fh6{pT~dW9Nxp~~wjq32;NQHKVPeGNKy zz+a9mSXIs3%ryQm@sGeVk-}No4VZf`h3n$0^_7(w&mPOagwfI=)D?f@Uc5gu!S$!z zpeInZE@ajL1&7A0-@zvtDd}d1hf|$q$ID^n76mw^6K+)ESd4Yo}!1dWxU8i zaG}N`ErB81@Zw1qn7g43sa(f${f%t@J#DW2IfCjfb2>x7Pqiwa?4Ebah0p{i#_y+q z7vUBSB&lxhY;j5n&c_uh8`kFT|H4)s#h#QTsQ_0D71+2fQK5vQvb0uzh#qm_r;hTg;CpA?&M ztX=rhXf!{>VHP91H0<{^Vy6jOB8)<_KJ3OQacqf4n%sT)*u@C8X-$BR99#Xb^^(3j zgJaM-aZlHPx5w>ZKpRq~Ha?t1)46H9jvnVoL~CF#Bht=~Yc3;LX#MguZ}7XUSU8Jz z68p}Xf8vrP@bWTYts2+AI81@yCy+nO;9s|Pp1hc@$;2lnnoYr4Zdvr<54CZD*m$sH0SGlnuHIVP8)Cxi`ahxLh5EX%P9s$Y#d^paRP#xMV>)9m0f?ilo zO%C>{k_5e4)wDVXXy%1=gPW8?HQ5kZU%(>wg(=1p~$2gr+5u zKsir)G(4^&=L*=y1X^qad`3kC<5I+F*`J4UmLj{Uqb$bO5{PQ0j2~cn@#RkQ&t*=U zQr@nD*Cn`r>#E~UQ59Z095jC5*s61Rd8ya#3T~b2{CNDw+Hu`yi_0TOa@!&i`$*{g zkZ)g!{ftbtBsUwQMl)(Bu9BLh*hCcZ3zA)}0!~2g$Z%uj3NeG=j7D%om&G%uW>9j@}ZUspjyE(qa0p z8$N4aLt=d2PA(SNmu&HkyWVCmVY~cVFp9?OXl_t#$kL9;Z1uI&}8sn7-Y>7gmzyAVm2oqXSG+9Qq5N3kM}0!-$S zk~Crn>mzDXQd3)l1`3L&-~Ort*jBTBm4~?x6ci~Q4$zBY{4;FR0h>-U9t+hV=4a!$W{b>(LTz%2uDeSibX`GhQp-j9g~@gS z`@P=JF?H)?7DQ)hw-z|@cU1+CeT+Ev`1tD=;KU6Pj-v(RDgGB*C7%Z=B@yKIEF*nD z1~T_|?IkRBI;YV5n!bI9l;nXb+^s1}+OUcN44WWovDU0UXN!CmP6_waG=F53?U!qx zdAMhpLpiNUl{MUU;G0&N^cv!GamJ(_+co=7)NFbABz9s`2b?VOyN&@J2a(VdMT0WR zETyf?sQYg!NJ3RzJUt$H?CCS_{;Yzy5xt09Bs&spVt~I z$Og@`=s*N^1_@1MY4PuC39rI2?88&UT-4FvXb&tT;+ndP;8c?8-^L@}FV6Iw-~U0S z`?0mgmB?QEARG|XbdDU5DXL&8CP@c;QjJc~8~dHMp+-G75BSFTDNW{mVqABDX7o zf0dwv`~`tHOBMmvMq9jSr->Nhl7i(qZZKM@9oLQ6z+6~ecXti&)_`q>19o!MI1^sseE7slKA_nV^ZpsSu`nRCNH@U-!ugi0&B2*D77h`gXW z1MZ_;WfAZXOi1Nx#4{T&j{(DMH%5GN&? zzfGtcr$hSz=N^&n!weY!MK@tHpyPwP$|~NF*`h*NyYEybOi)?)23fbn*-e0+#*flN z*aA@_3r3qjg`hq3FzCqv^HQIN<}*&%OV?Fa|<416>~VTX}%C8m>d2Tain_kls*vsREIF$knZ$lxt; zUJ+e2ok|uhP2~5VcP4AO>$TKNWsIk*09`u93}&_QY^S1gG^lJX)4KbW*5kQ-&3iv8 zRg5F(x;A9iY$#iD9BUg zgGfJ)3i9GV{I_bPKt=<8ABO4&Zsog69NkU$=ZpOwi8UE{F1LbmGawaksmy0Cm&;O+ z{X)>MdJmy><_4s~Q)}hyvefzdC7Ivw1uVU5h!EUC!S+5D;>#B~yP|OH6l%m~=S4J6+8xXGd z;|&oYeH?h8j!g9rPv}{S>h$*|aE@mI=V$5uZ6G@kriAE<%RWDyO8S(*{80vF1P53c z-)^YpDRFGNKTDU;pcGyc<&UAFhBL6GML$SP==4bNVSLAqn=7Uez-x|f83Nq#v-%p~ z;4JFfy62y7Ja1zruOIy>?B>h1U(U+mFe+P_!QI2$-+`)(Ec!Y;h_lol+Quj#ZSdt9 zXNQ^P8No&zQGefz(e#ow&Xtuy_Gd@6JB%ZHIFjxVu(#))hVI6V;7$vhTAm`B*UCIu z=aCKadu?%ClN!hS)&RY5zHT6jzrr1jadDJXg99F3y+ep}O0ii7G8i5H8KI93`jo3V zN6UEBe1v=bd<~@iWVKq=PUcP7%l_J3N9U#?wFr$9@q?#(dSrxi6dcNntCptWNXuxq z95^2MYE6R|8aXM3kCR+J10(ghTn#`3g%58lzzR3Bnzl%5w>-@+f{xI40@k17_y;#cXi?X;Rm z=H%xV=*=(J@AJi7P#uL5@XDl4KQPHrPr9y(a(ZdcrwRv|ed@O9ar7ruZ}-b-=vS!! zdPW1$gwy0{5=WsK*DLF)huzw`|J+pOC(<05xTeC*5OCc70);@GDr1~%Kg%Ft%5o~) zb+%N)~BUo2rp<}Co~1HHnq`*#=evz$+JD4%#UhO&ts+SzR;QveDzU-mX1>G)zKRr-*9 z4z4rfofccynDilW40Vf1vj{!V6?8IzM`_j)v=LiEwtbJ<~^ zjH|gOexi38AGx@%S7D&>uR8k3T{_n5I?*xZrg~QstJMAa=5XQdNsr3?skp#OO=6iuX2t)r}Ac_9<;63aRzFk)QGH?*sKLaX+JqoSbttgx`~e#atqus5S>xxi;Tt5lO*ASh4`yor9 z>lyHzvTyz+nzdiE9`*vzO32RtphA0gBqo_%Of5T<8B_FfY^c{6f>o4pJ5uJ7mzYeJZU8iBq=Soy#KqQ+3a!t(sjrb`_*k1LtIq{ZbEDB|!oveoNrOvho%vzyRojp}Ui* zTMOA%ZBTiGiNQjAqyhRvq@7B?0#Z$luhc|&--%#Zs|)#M)$#A_f;r4c?8}0cxH~$1 zp94ZZJViIruYC_xIpAI<|0<-L)S`vA)!y~By`P^x74I>qv<(SMST&rK7XG8G-WBpc zRuq3G8lVF!YS#$;piv4-;G)Dca`2q18-IURYtqjw+6~z}wCj>Y+=Ct0htm~4W;`a31d)P|CU^SG;Sn6+KgAkS7=|*sPS)#S+=A~*g7=SAJH`jo4Z)PuoNFGs`{oogj z_bL+aNAeftKaVEt0JtZ_gV0J*7gC2bEOrz3(oVc!O}~Vn>PZW*-A*wu38DY$R`1>k zv4L-xnwEh=Zhc4vwG9<>vLg#9jPfM9QP?EwnUNnglU!VIjq0N+GL@ew_v7wM6~~m; z5djv_u=(JInSH^6x+D@7&|Y@52@&brm=veXFFnH-`%#x#1RLA;&?dN=xuuGd@`(WoJ)(C4b#7<%gWnOxP^kOw+v3mzZlH=P%wcKZLZ6BVTTtNB9Me}n*fhWHYwY6V1MlAa zCP?5rD>|IzC`7m{ixroR4Z;k-enK(;zd216>RB-)M7nPMN*nP0n~124HJ<@7@-d0#7$hY)%*o z@DNUjlEr=5$;Q^U>coYe zxnw%u3*@!m2(UqR2817CPid;-ix_5cJby`Z{Z;gJt_hbdK;--kT}`zAR4N>@4AL*+ zSL%Sz|bsx<5v=INEi{(SSQ`F-&2eC_ zXuJbeaqq^oM^3DC;W0OBHE3@+ zGY2tQuw(CjcQ`5Xaq^?tcH?!B)z{(k{pI*FdUy}Kc}c)uq@?9-@y_E|L`vivOLOkU z0h+}@yJd#wTYn}sBK2f8*PghPvSp4YNxl*5X4owklQFhI`SM217SprIB|ysU{ zQ(|P`d63KleQd>%jP{cBb$$DP0pj1?$k|Lg< z)*+Ra4ZZTLo!&K7!y2la5oEOc-X6;M3Kf_W6;9NcDxeo#ih-`?#GzRSEr1OAdHtJD z{Sbc{pU8d-08kjRjP7fXYcKP7uG^3Nmg0Q|RU=oZU{_Cd3C}(n*z%P>W~6olB@p4b z!=e@_Li9rb30KOF9o8X+1=hl8lpD#!P(4fF%D^8we9_{Xk?#$B64+ucF{cg-!kW$D zUn1fqj7I#Ni24IjLwrX$eraTpzdRtx`7R}>Y%M(*Oq>l}ST$`yN_6*19FmDMk)5hS zE-!p{+j2V)Oy{SkgodU|;Vftg%|+LVQB*|(OuIIGm^?NQK4&f( zyQxi7po=Hwfw(-SbH0t#tC84F?%VT!O+&WQ(jlGTDI((^S_2DS;z=yyV1I*;9Gjh|=ex_pX)9-9 zlv^{A|JYZsECQa?Y5=X6`M?Aqt0Mi)+MoRC>#!TF2;sc~S)WG2US5{F`x|#Fw3Sn}z_~TqJ&L{qJ##Sk17?q6Ywl5qsdA zCzTEbfy||n=}=qTJ?*oYL54X@z@R3208tjnB6c+{+pp*n8gWAwQ+wr5A@_8qKvigj zSVQrf<@5&wox)b(AkJW+pp*12tVwibDe`-T3d7V(%)4)eq?p6CZ zG-DD0R|5w%lXV2+PaV5s@yiM5J^}yshS?wFMfN7I6j5T;SHouiY_KQzq;A&q*MCt^ zQw*ZejilQ1vQZ1LsP@1>y!8}&BV%1pCK3IMMzrbsKT@?qf88n_@YCfjdhE{=`DkuU zPK9fDf3?0g;r?np7E=IzWY)r`Nv0`w=;CCR!m82#F?rtFdupwgO~5+7heMPK#n9;U z#S~#iA1V&)(W+W>Uz)J>v6qlbRC5-sSJ!p-y8;~K>bg?gg~3buNu#%GGGY6I?M=_* zcL?aCq9yQ#RlbFlUf(FR2OQ0bXANsk+tlGn$!1yAAlsGnS>X@!((Ij}Zn2x9ID~)F zbhCx_*yT(gwV6a$s+!~kvnVVK`1}cDj=q5S^`(c^f7HJ*T!to|Yoio6qEUhKn$Y`i zrWpk`5KI78hG^xg=<^OxiJZ3O$kTkESSAFpdAdGvb75~$O%2c&dpO+jDyDyalVY+1 zhP4 zH7&NkjujP)#n3wqAY{N9T)JR2bfOU`Zp#yZg{I9MbUOr@6AZl8tyHu{E?cD_pb##K zlg|#s0w8ag)t21AHsvNa`Ew?&^4F&}>0uG_r4c}bLl~7!jJ4&5dB-JgyaSkn_oI7F z<_QBfq~WShaz*olPfk0S6w0EB2;Gk!v}dOJ?7QO}QGqV!{5nq2&Xp(V15!K7P*?|1 zS}YpQs+g&NuY$duTU*;LGIs1s&&aZ9q^BJoJdmh96Imx}C-8{)Yb~)96XV68C1&;u z=9(zkV2CW*A@ObVnx*3gvc7`}RngB(bn3>&&wm9V<<;E6I3IR=U47IuEng?S%h1Yr znncO>AA9!@ZRTW49hQfT{P2PO-#k24nQ#Xm4;?uwq3sQ|LhOm>LePtnO23GvGTWC! zc)vkS+lq3^vH&h+HfqVoryK~+u8)Pxg>$Jag99kfGc;9)=cNdaq=ErAoJ<~CxR@re zBQp|dqA1Y-4oOC(BO(`vTj>9L4oH%Tez2oU^QI!xb`AsuoL z^EWp=g|r)HPaZW<{k682bvA~5>7IT3>aTgO0ffL&UljJi!V7T{YruM8h4PU-AF*X@ zK!&oDR79ZDV=&Lg(NGL(dqhphqW|TKF^4~JaarHb=WMA8Pv3ji>~rttxi1(=KtO;n zZg0Z14u;>&sH_0&Z98TE?uR3*eG#oz=7Y>cBB&n%DyUSTfH4Az#;5s|Vpv`de~IQL zeL}epWgLa(iw;d=%PCEN*)IpVktAVEAN!p@VxwMJRCg@IA}AI9G`JPbtisU)46Mtp$S@DIt=YXLKq@k8|l9=ULEOWV~SBAG}~V3ZI{L zb6*x7$EAl?2%vY@GXPl{P&%$<2cpC>B_;SO5nuA{4A%a~(K&|4)pk*MVzaSr+h!ZK z(WJ3$+h$|iM$_1~)wHp##>scyZ~i1d=ep)O&)IwJd#x>q%P;h>Q7x0uk{*B-O1fzj zq(Y*`s;1Mr5jr-w1QVCiU0VaI70whfLp$UEk)G0f#r1Et7^ib})fK-?T@E_$lV-AB zzWn$Q=3V#J?5tIn4$ITdK6cP&!lptWHIvW5VT^_fseDj_Mv~`ng2;m04&!Wr8!7Xj zY za97RzJ=$%FkNWu1K7mX3{ssHED0z6%SJT!9%Oy~DN({@^@{ddJy0hNrh z58{C<+YX~siPae6&!X+V=PWQdXs9ZxSkD5$LuJO@mE|S6luxkD4oN=b)@Lk6%P0~- zWcX9NfD$5^#sscf-{fq~A)Rem!f%kT^+Exhnlxs@MNqL+^L)pV&nku4AA%Rn?FN?o z64*>lhtZy9%1?xyz(<)&K1{C|!hBK7{Ra6_-x(vNmt|ujI-!^Gn3t?NgT(@hn z%JD1-(_Ta_xK+oEL7;}MgS+arjGZ}<#MAY`_c(nH{)es`&7<)W=B z_0M~Hne%1S6&dZzUnRWv*m6ovblNe4x0C+imPBLctK$RYCWXB77T?#U_AovB>mZk( zmRkPPSiAT1^cB&Wx>f&l@FP+#xAntvLtmwqkv0k4L@(3}J++Og%J3(0T6mRZ`2@wC z79^I(1yMK|d798nBP`X9D+(EbXW5g#RPX?ENYN{&mvb8}+R4>?sY}3Ay$%ZiE*Ukn zdft}$xdFHBoivtq>b{Q%Ym~%?x?dN&*u0!sgBF`DX+g!#i#E1ceKC5c)s%DR2uA5i zD8nV(7I(kFn~f?K!Ro*xu9fIBIP~4TDPx(+#oCLkeP&&?~fwz`ip_P<+FAYacUd?CKKEP*9tN^&OZu%l4=Z!@w}b z&}0rF6CR9d=)ha>;zJTs_&rc7-E4`cbVd@+mwJn|Al2`bS=!s%$9cO=lO(UZ0*JK0 zEgU`6Uj>RB{rB&m10V2cHm%vP;Tz|9#ltuajtweA69t1z5p(`So$ zg-e`iZ_K4D_D->5><9CsUR;KB1ctFGx>#9HQ{lOjj|WZc1Ut`K3yf>=Zn~&3*`^;a zA~2>ie)T!k7y`0~r7Dq29^W(YrU#w#@tVxB_K3yD%uxj=AlQ?~B$6ic*~j^-^Wt71 zCcOp|iOSibC+Wj2TlSUlg+C=Lcnl+tjI921O12yn;1A!|g9}M{J}<`?(+!7`^3mXz zW$Kw;FjAXKjCb_J*M$6D$?=VZGk7ud<+ArXFOy%YgKBQ_1#N)68V#O4&kF3L$cAD+ z8ONgt`W5>>3snn3bD|+;jTiP*kY0H-l9K8d1ZFJ96Y517(6%3Xz5{bUIkD)LGWz2YNU}VYd|*xPTwk-rnBaysWYk7z>$udlRyQa_@<-17>5VC5&m16BTyd zhc<9&ipUy`+T+n-0)tH~e@SroF1h4HpZe^t888SGtxj&UvC{@w#l6LBe;R47_U*f4 zy;VRUe|?(y&zJK$(_Rb6^pfxZE!A!uv1h7S6^_Kt6TPKVM%;yA&;Xj2Y%!%tSQ5t= z-u3RNwSa#=s@zo@{dC^7Qr_@~11VB)&NFB0O@I@y_5edz0BU*cL-X5ua1bKN6Lhz8 zcX#K>QY`z1b}EY&o95WQ4FpIDeJixfc(6(tORHC2MS1)S1w%j!Qc{Wyh%ZC-?$Ph& zzg@xql5!LWco7FalN7xJ;xlo*#eif}3Qj-OLpL&^UltB!>8FmWT6(u5g zH3N6Vx+8qo$VIi68jaVC_%Nz>`lrI(iAjXI!qzH9P8Bysjp$QE-r^kFC)bE)&%)^) z5SH-=3M*Z=Ex?qMKj(`gdKG&y;Xk5be8awP(+dgw28F$OJJ>@^Y}KEd3ASce#nONO z0*_(+VUVDKv$3#Qj&CKA{FGRaz--Q~(=q=FEg?K5^QEJdOMUrVC&e03v}fkCYc(QW*PrD_y-yRK&XBjv zF-=*Mkb-7z0Yyxb!n;Oc524XUlCV!fW~eTFQ{J7~lnXivKgC3E7V_SkEi-3CUXZsR z4A}5uWrhQj1O+i@n@Bm}dWF0j?Qm2v z#>U3F49M?-=|C>Rjo|U>!`+yhrsM_$gcyR>G|VUg2oHr#2XEzpt9!!8zdygCW(`w* zCQ$}Uds|)59w466JKe276`F?SVilDMtWx9t69eA-?a(0ELB3sr6pn8)zlxaKX^7xF z!TiLtRqQAhG}AosM7OI~^RL5VDU5Unm@uER_x1CYf}xRGHu42n&3EDg*) z-B!9#dSNDBrMDpae+BKH$j`}X8k(~9BGM6I^jt=9Ycy;T^-Ts?t94GQ*zRQ4pYA-= z_%k&lqJZ5bWMakFacpIt!Y%bJAg>PBLs<2i6{NVhTpK_ezbNEVasZ;_X}KC({=gHMFcMtpUT#0S#qO?c0&`YMczW`Q5+3ZTq?jP6 zglHvvk63Jhb-*Q-;|{RLc#|cA2!c`W5V^Zwv;B%3@>7mT?d}5*czEsq5}}6wN7jWR z;kL>qP_uyF6K8(@$}mM9g=W@8ukX8{mPvXrTChPGN^P2NNlihWvx>*Ze;4^xO9&>6 ziz@lEcd=~)TPjW`t^sK_Y+ctyLjky>mQt6S%x4AnDYnS1{}U@F*X)_L?_e^4i0P?3U&Z*?cved z)^@CX3UJl8LZSd#bxvQzy~ijfp<8oI1JF`nGy_#u$EDBCyga-n1BXd1MuG8#9a2K= zm6b71=`#ebrlh|(Rkres*qID!Z>d`$SjEv3;mthNDkm#FZ?H zonlncI-D9LP?6{yq4>s;wK9C}Z{}eZ<06+HjA`5c2Ed|<-JV5FMvo-;y3{2=;gv%s z2z+67tb1fnY4Uy%3v!%OIbFq+v;XIu;5YXiM1j z0D}nYWTZK~L7UmrteHaq_5}DO_lu3O+t)wto9Y*$(N;Hq&@g_IpUKvoclK2ExwVvppHidZn4pMjMR^%K$9mv&(xYAV-2`GuUjuZLPzaDX z;RTz~G=t1Z&dUMh|6?OmP**`^(579WC8c^~91|{17fe8>e}h$GQyhWil*7A*Ly*b# z&8zkuEj~wxS#jM3oC07|K(t@q*tqi;G~sA-+8@smbT?~Sv)~eNK0ww81@nhhl{b^0 z*8<&V*~{3DKKmN`W=PR+7VIgPm!sFC#$!@xc;#4>Bk>uh~DqfY^=G`wBmbkPR}22{vUa5 zU!HU6b2&&iA1@Fj#dt3IWM-2fG)Nt87d;@jB~Q0rS}`^_`|U^B7J1n>1&xFix4BNj^>?zLpdma~QxBF~j#<=kUS)($ih_@omZQ z(!%51;Ko!>r>Y5vTa*CF3Ia&^pV{{x0wIFV6`4->!?)XKZH<3X4a=!MD!+c;a*BNk zqrm!V;aizdxctj?1@sl?t$dpJ$uDpkvPQa|8jB1z9Av;wXa~G^0rq0e#tl$s8ks)c zFF)P^ZH7jVgNcHQLqz}N#~b^NV1%2N^a3r6YKiPEvy9GPg+xA8%V}$^xzPm+pRnU1 z0!nrAX>YR6ES#cp)w=~u6Po(Iu55UKNs0E^VQqa~VuqbhlExMS;)|RqdX0TrT{uh1_QYX66LR-;gspI*PwIV@A(EI6NTHCBx{OinGpqufhI zsj>vA=3PkS6{3X#ro5gn^zEPX>>4Ua?mymt^jeluYX=Bn;H7zE5wssdg1Uo;j!J5R zf@Wjil%8CVd8A|pKcOrVf|m9b5I!{=Hr%^f$%1o^C$p7ImF*{nG6>RU}B zE93;cMNN%!O`(f~vLzXtrANN%a${d|oBU9AMsP{&pVU{JHSW)`PzSB#9Is%kK-%A+ zv!)H}iiAmy)UNAF^VQOM_zP_g0hYp2PSE#&3w01M}qj8deOwc z`?DLC%$CN00ahq#64B{{NbZzhb(*i}-^QWle~^!mfWZ3i-yOhg&O^v=HS(hmMs+J0G|HxS8oZ~r(!g>; z>9Vs~ALG3vhL5DrZ#z6T<-IY5TpgF?QGDM34$sqw^{4IA{3-Z6X0&$4&6;0jJ6euy zI?JxU2a_4Kv(x1hCti{gBV%9gGz>z5g*q*W?$Zs5qkC#k|8G+TcsJlG0w_-xf%}w5 z;H`@z?daf8|MMp|5vrqVI`yD)N#8l(Y>FQ_Mok_5MuMioh`i7_xpYE`GH-Sxt?O12 zTwJ9wG!7ymKb2Hk^%c*^CZA4KY%)Gu)*->)|_j@Q=IOZ=#@`bCB zqnob{95MDZb@EzZr<_r({;Fh?!d$3TzO64zIFl`-fru$n<+LhCh)YaY(;A8&tsqXl zb+f#g76mMWGFw$Z4y*kpBYeh}2{_`qsMU-DL~GM>7S_qK?6+fTwCzBU+oHG_fuL=0<;3mfG3UK zFZ-F`Zqs5n2)6ti94C}x2$R2V(cghuP&MTqD|_xO7H3J~tbhEw}??IUB@Hy3d9PngMgMd z1I1sJh721GJ!71R;gUe`gy&cY>M`K}&Imx91Numn{X92#Z^W&_B-p)BaxA+Z~D zP~)RIeBJkcJ>4nGznE{_TK#$xMT0(VYMp`i!pQeNPHqX5eN7J%{H^f9!Yhc_7P1G} zOyERc)@H^VUjeId1er5{Sd?KkWUJ1|p7b?}>LGp=Ma>d0DHZ8h{v|zTl@8&O$0kXw zZGEjvoEx$yOyW^j&y&vz$VLu)OcPGV#>VdM4}gFO@WPGF^w#7d!2BB+cni8;RBJG5 zLFCE#?M$-#@dRY?JSHDWo)fKiH-?7gDwfjHm0wpx+vWV`Y9{@cO|&1LUoHKKFiVh2 z)d4!QcPj7hv&`N4G2Gjm`dWOC=$4Cgbn?518|n8rcaVo8W;tEv4G7MJ=oVX=J#PlW z{FD(SU!thZzF}C8t>vjGM?^}M-)GQUlOIv(8C*>~hFT&K^n;Hg<7SG z-gZ6u;7k2&e>ZuS5w)+9jYn$!J3^r5B)<|J1A2nP&|v?;1Rj5VWi?6Wva}ZYBHKp6 zP5e;U+(!~A`Yh)rW(3`9{ zyze+47vD7n#*Js%b@uGtciOkQ)s%NrD*c{(NBadAT8 zdToOBi;&5as`&NVsJPqrLpBIC=JiiWn894gVSx~xwi!AlS?c!RB}*g%p~FjMz~EGX znLzLN5i$Ro?6+dW6Wqu89+gkbUYQH&n`MUhsJ=@fb~UPhceGfGBil!h);|F_-$#JQ z1(3J-4`hGZp%1as!$GhSrjYxESvPx$9+ia+Y#TMq%I~@a+!9Z}zfxin%DSzkXuh=Q zTHdM_Mk#ma4M<(K|C1@28y*HCqn@8n>-4>jsii6vuKc${asRV%tl6}*wMD|1F>rN* zdcj)2z63$>y0nDYN_w^ktouM?ssbe8yFo)z@1_s_T{YUmBp-fnTiCk#9H&(-5*Ukj zHI_;X%{N>eSBcSHfhkFg?PY-B)=-oR$y4Mz8xiUn zzE;r*9SW%pmZfz*C96@9<^Zo@BN~OS!85#MpO!2NXaQbmoiWNu9V!Mdo2+Pg+=n#e z7${`IRAUpk_oLprTkHBCew%?y50N5xn*J==d-4%|{;rMqw`Djlpz8CPUCk+xEaD9x zX)8IeV^AL$4p*%{)r46y$~vlRH$ANGG|AfDE4F?UHf==g>jEe0B8h#f8{wnX&whMy znJ9#j9}92nrpV;OM0Nu0;tObfWm%^(>5P14&J|;$Vval$HBL>qg_#XML3wZAg4 z9#LOD(R6|AHaa*|O})VllCK4tWtSTyGz1f%T?rvH{yoVIC#ryR;;+;ed@5I}O4zJZ z+s4{|A0UU}zjnFJ`EZb)U#?^53itrt_E>G0m=WWWAE3JxNRVuQJ5+EV=qJRRTP$77 z5XOV7k)S~{TOA}u8fF-f)PwG3=MMWAt*1rJc%(<3KR?BwB???sZHhlMP8HJC>UCw-g)if+=4J3Jm)dKs z^B|vLPilXauqCzVSfs*q$uPFumL@oC_lHhRO#x?Eho!0#utC2I|GjNv`hqn-KSdi`=9;eIWNE$R6)|<%=}8=M zq~DcY%~#f*8&%}llxCZt2a$L5@1>*$Amqr+l9lmyNV&JV${5xyO`etSFe0@fvRK5L zrYtiVwTyXMgi6h#UIYOWUlAo9TJWxh@Z(ba>{8bBpT6=I7@P?qX&StlO@mG5ob^+c6FwD7?A5CYH-l>je#D%g094 zU>#GY-XUlKCS<_r+p`lS;e|}k?A#=if-w{fSn`iVi$0oCbo8Ec zIG80ZdT3_=O%$-qiGDoI_)Z1zUrMXK{@Hxf1*iTe2l3k2+7|o>H2GZqGfiEY|0)={ zI%wTz7)X+Qt_KIEqVYfHt4*WOQjWqE$#l>EW8j?s{foi*i_hOkZ7F zZ%NVKfotF+EG9PD2?L(Th~S4f8dfQ!7%)sI@)1f~?i$`xrS?6x_``{CZ^_bdWLsuF z^Y-g*5xYIP@4|9;hXj=SGKrxTufg}lJg62)(MNK8wmt=>13XRm%ZZtUER(CRT}2q@ zmrZYx58Mib1CB%4iVXxizNo`uIRwt)ml%S`KCZShJnuro_OI(1&LLW)LUw0=o!Ypv zDS3Vj{flKorTf@Ov%0&6@ZXJLq(+o@tu~#}AL-`+*|t>|J~PO?jg@!fiQ!){QrNQu zf^uQGX0)Huc~ie~>&?Dy?1w^sz+T|&nL!r&k1AbrN{;njsLJ$XVq&OQbL5WEaaXjU z`7NCvMTdov728B;qhd-(-Wy?%rxJy7h`8Zp@MPg^Y1I>B0UMXw^Ex$cL?&U-UV9tg z!%l{}K5R?|OT=+*rMqKae&~H8ViQM=kgh6b?vLIN+}rdv`!BCP{+-vA^jTCt)c#;# z<{*i%YP&PBR32B3Ab!^(XtL_ycAyb)A+79b$f=ea6pPhv1ArfZUoo!04NpOO_y3TwFJ4*7N{mOKoj!0bvV= zGkLfe=lIe>tW;H_+2p(Y&^r+_pLOh2ga{Oevs>ze%1Ls<+?XH-7Ktt}#rQ)ANkbzP zkD`_h(ldm&9LOpUVP$;@sNd-NM z=5x$xhMxI?$aHJLwGEpd(yJfYW=@55134 zBnaWP3Q)pu6Z!+N$*U4g|A$P&a@GYw2s=Z)u~fKEUcxW?#Fo{tK!Pc_DZ3Y$a26r1 zk_Jnm>bd=rYrKo!!O6VO_Vf>Bug=eHJH!z@cP=T27p@F|cNw{KSi#NMZG4;r(H&CM z^aSp`a=Xs)0dquB9Nl;WausXhE|7vrW^hu<&sZX0RrT~!OnMV6>I5Q$J8TqUI`-y1 zDe~5qaX3G^31&h>zJYxb;|QY&uG+1Hpj)&cek48ieF=m}pIMF3e-c;Jtp?>`!v9@eeY{8Gk|HURJZLFv z!AE2hIL|;(j|G?4VUBytuV47kypPrI^&K5Az-b0j9s%RJoxME}_!L{6JTcQi4M#gG z2Wav((EIEf|0I8;4^Y|bd~jtbD3tbYF+q}F2pN1v50)w?s!vDT@sZ3lEQR;Dn>_0O zCAL5ck&bZ4b+3}DoN7wy|LUlU1<>wj86FezpAeD%6P5s-K;-3&le~M>LrA7P?6_Yh zfl5N++W?Ob^iFK2je>O@@87+{U84rE#ISFeO8mkyTjyel+0U=jFHRZ1BS;<%*wU5C z7LM`e|f+xo9y-eVAEsu03yRBPNh@yQ0+JPK*}( z0A%XL6a3hFNO2#HyVej3Stf&it6hoePs_wc>=dYjZ*9B~0#GAlaE7SBG1dOWndX}W zEI5Kk*vN{=E3nGXJG+`xM9cM#Ylh%7e%_s}oAMh)7T}zVsQk;3npIa6=lXCSj-w@n#>D>E!O5` zvj5x0RPP_EPL+G)!WG$wFj!ckACh*K<|m{v=<}4Kv1L?7NbdGh%y&JO1k5R}9q$a! zA4{FDHau-z1k9PUA<%DS*B)sQQUr<8#3G_}m28QYZsG@&mQt1P0O_`VDN&nY@`HNz zgZytMx+bnPI}s{|aX@-dtAyZZfC&N43{X!1QBFYA!YQCKICO7WbCQPy2M2EgX+9JC zH}fT50CO-vL>0}!r@*G*nUe5I!26;(IAfQy`+{gBIpd^sb9P5RBMZgW&2~vpF-YnYSv*q19RqE!-cV|^#GXm7?MrgfWc`tAWBr#b!W~TW~v12 znG7;NMUCG2h~&{SZgJ%v$bLNU>~|!T@i>85w3lw*gkf(^As-)6mtmG=v4vXu%1<3> z*l}9wh^T-XghZF+$)u*1r8}<2gi5A4Uaw7;H_4Bvr%K2m)Ah0cl9f{m3A2pU)MW;= zDcLmw&1hBzA?~yZdNy>e_o93TA*+Xv@x>sFXZ~ci6^ZssmA>UaFvfo<SgMPg6m z58Fj2k{Ow7gDo2vOdCc{B@V!kJ~V?2h@Zve7L4zPzFZh8sGNq1IM1#H=}HgI__z&r zBNsJ6K`g_H@_8yf=FDrxEfCiPeeyaQ6@j#5C+==U>SP&3evCqic@Qj+R5QM1Jo%h4m|Dz!PJf z<0VKVTT=vEcJ_LTc7ib#{0Ew@a3F5{;$8ezwg z5i_z|2c)0urvdR~xpwEkv*`acp%0kw95Es?@iT?!utD=4QKXFB;^B$hEofZAr^t{F zDbvYLPpDhowu%>*rX$b%onaE|MK_KVf6cuBF=#iC@+2mfE;rdXF6ibR@#N-&4Wz5t z{)ban6|KPHCz*C3U+jvz=E8gzHVAaa(S=K8ln|OhUq?pY+Kj#vu$y4_IrJ>nzS54= zBHs_kfGgmO4I(D#7KSrCwXG%DMiBUKPFCo>=1?^LcP>0(=h`_}q!K^!Z>(+)Mx|}4 zwYY`$r%&JHRYob;f5M?4K6h0uML~T2#&XaP#pR%440=WR+@V1b&}^j97J&kt$C-K* z3qrQWIWfe-3+tLyh4KE<=Q1tHCuR0qt5*IhiSQijOxsY*P!exM4QSALs>JT4m6N9V zzcgmHU~Ai?J}pEMoI9kb%S;7qP+@ahW0HP%3@3oxlYGF~Cf2L(!? zjZT)-BnF*mdYzPAW95G|S6|}4eVDPop4vFsf;9|tx{4!}cCXRiRubL|QT>HStIUW> z0U6kbfqMnSp}t!68^hE0Rr2p%ESLLQxA+hASxNly=ar4X0fx6KoXfeP)}Ef8jt+0Y z?so0*3MAq@pRF}*nB!C1R@^A-uHdrhsO$sjpwI-*L4|2Czl3tHR|QlkDb$;|Ww(nrBUpnjA)zHbMdCgq+N)gluK9>!suACMg%< z%mtR2$|6rxAy?y!b!>&qN|b^#x4;C;^QX4&<90ZO)5QkA2qmnctU?@rI6u*M_EUHA zRmq*wwIq6pN961UE|ulU$b$g>cEwV$hJ-}EMEM1Z0M>a0+yCeOZU9vTV48JyPO|5F zJ~+(vzL?D51VrxJCmlts;u>)ix36s+z%kq)LP-6uF~7&@=u;K_Mvv0vor11$NE5OVBy zU-R>(f9dAxXoRr~sBER|esNThsMSyZ6mql5xU2@jpVQ}S`3o)hH)I5noIs}ouoiVB zQ>IByw918+DAZBRv`2q7?>>gnKYPyM!b$8sKpUPG){AAe134B~hFQ_ZT)=@EAB))nVG>c?mM6L85%OK$6v*c`2l7FNFQN!hW(ItOpx~@FsxXeo%w!xB zb2-%Qc!2jrsz`UEg+>jI+nfPw;hzTsLRkHX2r;}NKn znQ@|lI=Rx|8Q3{tks>ICBKk+HeNw<^cKJ>b@{s!#ZxthBF`$9OX1VDbh9Y^g(Om`t zKG8BqvVDM=*?iFm)u+(Ek+8gh8N7-b`n)(KCRBBQpPkWyf zA<(Ox5TLU$|KvUSO#A7Qc^i(1K?3VzBVgaZQQ@q3 z0N*d(eK$t1M6Vi3IbEr=%V(PS@ALwWDN*l#XD$M!&v9$tMQZZbN?z0nl=qJ? z^*DLek5jnVTScuQy}2zdU!tXcJ9c(D-!+)(NXF;|@m(5S;yX~(0~^rMJWPd;=fA$$ z1kmA-G9%ylv>XbndIyvbsND5m9&5L*M0WxE-VE(Dp3rZwVB!!8c`f?OaX>Z32^d_? zFlS<(us#R|7zxdOQVp8W0vlWb>G4Gl8?6QJ5Mp_f4(Qu$_Pvu(gkKFwu%uuU1hS^k zzcTtFJaRvPD|qs?B*h)Fq+I-Z@N;o zj}Q*>-?3K}?CR|QB8G2zjf^p9y9V&)H2{gez%&5wp~n(3@k80|4Ml$nE{}D1Etdt6yUfOC*J4y_`=zde@h6Zizx$$#YFWP=_ zwXiPvkBUB6p)MCMzz6VO0O8q83ju;Xr&} zZ6P@IXTao&BNi(fMMvO`xTo6d5N>iQ@kCfMYcV_i~RW<^!m(j@qLD?UpGbmFNee3W24|_T}8V3}8UAME@vPNce?!&6`c)+PC0N zk}dKn(i=ns1!?>HcV#7dHKPM;of57W;BJ#p`p+3e4WCb!ABO0q4ec5R`BM+HpN2pU1u+JsgUG1kEeu$p5ijRdP^A zONx{amWu<=w>z>p1yJ-=K5sw;>R>PnZV2Qzp@cHJy|D3$JSH_+6gl##Af_Du4QOYv zGVm&<(-u=!`1)c(piFbIInEN2_yM~6(1I$*eaq9_J_SD=KJ966>rk(3a^*&;^4=^l z*_&kBa!GfmM}#3}FhCMNKqpYl{wePol~{n!omPXAYx3HJa)d-4P(va~oCjnKU>giz z4q*5IPAurmpcGZ?AJfFYhldX!)I>PM0T5(sYM7-Uvpx#?$H z1pmS{3&nS|JpeiIQ;MbZd+3vQay@*osKOTk%OGhz?ZNqBS@DW!&_;4ses{{jeOo}U z2@E~{OIk;nk}LnNCixTa@S6(cyuUy6m_ra<3@joW{y^exUC|MNY=MI$-mXtSd(^lW^$F#y^ zE)t`lCn+e(IqN>1g1IwPc`fYDctZ|}`3@c$#S1!?YM5X_L|AtihrzadK(Yp*ko*FVoCz54Np0TkX_+6Ts$WbD9NAjAsb|&4 z6+AVvd6$SgN6CYZXSR;#)r(_KB=j&^X?~ifH`wc)JTq>YO|6kxsjb|52&Mj%K{4=E zBU5nen{o1;0S2dLhRuKQAc&@8@AK~{8QgapyyeDEL{8_nJBwPv5i>F*h24*`uJJ3n zzpeS7c$L9mV-Yv})~PrAZGs~x@zU1PZ{Y9X9CC086a~DJA8PU1WvD~6I!$M+X@HKT z=YX@Gi-Z1NcmEORx_{DMadM)CTwd8s#ik!xcd!rCA>Svq8^^K|;H4~uu6J9}@)1@J z*6Q&NJ>5LnNRbFwtWRM1G@z}d_pF=mAKOypX?P6fGX4n{aAptZo3UCq2Jz5bTwVfg zAJ7wa0G^S_Fm{ep0pQ3yy}w*mU3>sVY1nDOW`BdqodWxCY|frCK8Y};Eb=C&4KcF^ zn}G2+8vHOH5*r;_zo_LY20qwx-~w0HbU#j=^jYQ*u3j)MV(E}uZrJbr+}@uMHN39- znc)}fW3R|W<6)k^9}v~Ppe(usuebo6bW8?q`T)7yC3Q6;ja7_%a=&zcw3K+8+O=`@?nVc*M$Bj2Z_fA25?Q{%WXz(Pj z?mcm?8sMpqS_S6BA9x1R9}pHyhz?(3@QXVthp^MT3mKqZG{|edhQ6pCT4b7WWE`DZ z^_S*UwucAz1=I|$V&ZdBQb`Prb~9jAU;ta90HApOXJrblzJO$5#2d7OJ-Qnd1?7r_ zGXgyDHr!dqtQrsS50M@{fFOs)W3JaqZHScQMC27VaGLciK&;=8uxozF*tS#fQvD)X zS)JCy;`c8wpgL(=)94+QW_721}Sm#&QVXepLFJVlY)Yi3m zwSd`)gCKShR*_TvO(wbGj-wA7$h7_jCq|%5@oYcnA4mVOjrS&M_Hnwcdx z?d>f@Vhu%?{j0UFVIprz?jqnl$R7og@w`^w&S+Q$&zzT@2$D)A!ebMJ$eA-VW2p8| zTZ!E9^xi)|bvH@<)!?u|Ick=B=3qvT$JphaI5TSkmnc$W( z6<938Bm6(5rn02JTDPb zA+p%JAPn16LpaVy<2&I(D*a30-WE^Y``}NNV{+ z(J<+w)!PGaDj-RG7c&`zrgZN2u!z86u??Kwk!pKb2Ow0!#t8{MOj|6_Ld_WpHMhIi@7?*^xGge zY-UVQXyv5o%;{|Fq@x659ChD5%7Cds6cKG+wLDA?#b1=G=fwRR^+`W#pFoFyLr*;B zE9vIN%4f>}dh)Zv2N;3b+8$diz6Uolp`oI#W=XB&9>^UV<_&)WBiGM=j2!i(LM}&% z{xp1Baa~xvZ?x*pP61X4{HmO5Or?>Ns|8d)X-ZrKif9@iUp1^Jso}MfJ_^B96s$3h z3aQUyCmy6?7C{7%(Q=~_K%?1Pt&rDtgao}lVXID+jBCnP#9``)opAPd5J!}0yF`Z%M>4m2|K#UIiVW0C1|+`jd4rKXg@c>~D8o7wMGo@@G%sug|+= zpTaNO56JsXcm2A1F!C=dS%5+9fIM4XZ-+Qq_vIz#{PIhCkK{$v)SxAV@WyF#)%I~S z3@B6_!a6500$iC)CNfbUnkll z-|Y9eGVn||3apAB`pw)|2c2IP-H_vW62R^`mh?XchDFK?`MvGjJSm}CWq!nynON(~ z15$Z`3D}ix{G;n9h^h4sZcAtsSTY(5TvNltur%O@@TsIe2g6`6m=RKZIjIA`^C#*F zwM}3&e)*{vaGT=;!?E4_**mdaSK{{HUfSILv)rYE6$<`uRc@hGH1W9{CXmQ_r#;UD z25cZ0WIw14*FJfI`53@_%_dAZ=`?^ik>#{JG65w5CstnY1qw%KV(nCaEhWv{)P>Yx zG+p?P=tydNvDZ&59$qsc!35{#Yi($~dyrn|QHYpTcy!M1rwkETI?{dWKO8(0wRYpZ z^TX!FVt^DL2h-|g$QP66_?VD7ZUwvxI^L^!M@7YSIuDEg_b0-@pe=r2dFs00XzMdPX zL}ATmqfI0({xG$I%wDoSBGmwaQvqpZ%@R3qfp0$+$xX4b<#N7W7C{C8R0#zzbRX?> zyT*VEu^SkisH^L?Ihg|34@U-F8#H@*bK7miIG^3!I);P-Oo)y+X@BwUh1X`)$)TTA$RbkS&;ooevr+x6N@l)AIxwc8G z?idd-3-(wMgL$(7)^|n!Pj~{x@4$pn8?d=1rO)d`u`qa}rIg;p}?n0a#m?ww;$uECE zz220rPy0gEm69%`N-n6p*T4qY<%dm({3}LD6%P-Oaz`z7b-)hIMbHHV z-;k{^Mj%t5-T82JAEKj=R9NKrb@Yz_qU88IcH)qcp-qVTa%m+)vzt|YZEQli;8IlJ z@TiMG4v>N3D=mF(R!k~J%MA~deV^fmG3O+gJx;H#RDKEle+^Zt>3_Yu#{N9uy`HUG zIEe^~_ep<-eFHLN$khtX)yzQ{%xXUZhK>3$J~8Ga+Z%!zS11vIEIvLyJ|NQvs8u7t zuI5;QFu{7B3!rZ7qHswLch_>l-+;oEp;My)giQ(x2`%PpxL432s++-8);_W}!nZ*8 z(z8TKDDMC}GWW|&QvVyXwZFQc9p3U21+X8s?*q$VN#YxXw3gtifb;Uj8Skve4#zsC z#xA-Lh_(jku;+tok4`Nnz|;8u^_g;-C+&YXH%a41wD;%1Kz0mZaZRuX#%VwnD^5o_ zPlaz#f=Eg=ccud86cFfoPr~E5oK(dhR*LvcqGe*7dT`suBBA8%@?YrYh0x01=1C}D zHs2YiHnn3~a&;YD<_&@|SVFJ06Yo3y9OoQTa0e@0B(f#RiYOUTb>-)FHWmMNulq_j zdP^nl93@v`t2JbYo?LoZRA8JDDfWTi2WI@>VtW^sdAYp#h=Y~G{N8YGV6dVBAaU`|LLa@Yu?5MW&iZ31@tg;=T*#0#A|>5ft+e?fW` z6eL#O%&doTPKc{vIWcm1aq)iI^KQMs^504fS_4ujz9eDi@NMz2mFORNz zpn|}IhX~(%4P{1v?v? zBYYwMcOUrwk#v30DW(0;eUUF=WJ>Ugtx(Imh7#r>w77`Gps9`G8zYj!f2eT#+C zI6sk6b?4N;f0ns|aIzz~51wBeoFcdcV!ca9CsQFw#2}_zEkDDu$1G-sV$>i~KUMnO z@6O0?U874zPJVoJlwx^5``+2n*_rgG6MYvWOiTkA=#XG)krQOr8o)FYR_Z|1qu|Ur zd41y9QGmaRFg}>aNBzbIWq&N!#EsR405>Mh_pLjh*{6(#2R>cKwM&g)Vcl@r2#HaI zBFqX}C2X-M|M7;*{gpHx+qzU$#kG6+&DTZPT*5vG_?vxXwE>E$mb-tld?C-bWu=QN zE3;0<60KDGF4wY22HKEF_;5aG*000hECxGRk?lVQn$XCrlQwdaUY(dap~ll3-aFfk zAOhxhRF>_it!z?9eZ-p1w4eYYw;Jjn>;ua3(NFv?+6W7buZZc4T2<{foY$v^Q|Klx zs2$tIP8<Ia#1g%M0>{YfcSi2z&~PPzagSwpAo66ms8M70cl;3PjQgyG z*3_FsIE?S-c!W?gv{7W0U4-g8Tx{RlsIJ%M;Tk^Iio_4bZz|cQQ8=Lmn=h@vRc0Y5 ztz&5R;6xRqyj|PH&5O^6P=gfkf9MWx#$>)&K4CQSPEgajs9|gJca=W0Uo0|5TvzJs z2%~SXq@^;2Y9GYAXf-}0rX|oNm-%V#Yq5T>NE`bgM_;v0p@*ARLrVNIQ((lFE>r5zDOJuH*0ErxiPw3i+J!#x$$sp z5^Carw{2#5Jb>x{E9x!0qsPr;S+>;X?+di7fISLGcLZO6z(qR+J8CQ%+N*dhfgjUv zPtp@X01u8lq4z3b_XD{=TtJog$GcIVOBDmBiO=s7uo@-NMlSbws&fVNX>Y#tNwdR> z>}b)kAJ2Fkds$W^Cam~swm-$?7kd_$jbEsivU|@h<1Ufe^s~UAt^wW;Fc<(E1!HAX z<*L^vI`2LV3UdB$IZ_{3bw0MxgxICvm6$o+lsUr?({d+tG;Eo(*dUrJlR<2o%{Ama zU!-iY?i8wJme(ZHq;f>}7Ts|QvrTMG{xo!BqIImC(V=GH)E{4mQqdRVDhNhSqQZrw ziHFRS3y&dV@?>D`b5)jRmoTDsVnh4>q3juRpa@DJls)ePNiLun1GH@Yr}Kr?)^s%y z?;vQ?w>Cp4bMkI9I3TEpzq(2DIppZZg5@(J@kq- z6aj|v!7Zhu&r>Rl#t>gur~2*qZ`00AGwcoP8ew?Fl>FqyOyR3|q#t`G*dI!IbUxAB z?!AF}#e#J@?=`f}HC>i~x#Z4Pm&!74y2qk^A!d(wD7g-|PBg&?nrWOtkmB>RzXyvN zCUU*1%T}bXn$Jq{dD`ZSXW$9ni`Hx)ZWrgt7>tCn;T#~2*Tl>Abz%lj6tsUD?c0V- zc{OnpV<%~mV*s3U`!1%}!aDuOtG*f?Ipvw!BHM!pr`Hv>Qa0FV*Ne#v8Z_62NrZEx;?Q(5FK+#^35PhXo=RIeqK`sZa-l->`Zewh zf7>}b+ZC6(>z%3{@EEY^QB6jvPcmjs+<4VkhA+N3w{h-&d*L8LGYYuhp0NXHi$KP< z<>2Z`b0nB`m|{M~VItYkAphqcxEbbz8lW8hY|GRZ=RU9XvUlxX3%d zyks=xf_}G|XP`GxIn>{7hOL}lpapG}@iF>x3HNFhcHvgUPet?O;Qnae9`;;;=}H%G zF7;;D-Y7m@zReiSdMqx^+~Q`urS3Sm^kB zIFOfIrQ_=UIkx)SAJ&efSQyZb0E23NNaDrmg3Kj$ILxgVAwG-`ze$0Bki0Q)-~!(( zmnHq2i!)e5j;5y(*&vCJ{rYzBgJ=ZZbb82Wkyb>1*!}bZ$M7HA@HWWvX**yIwY12| z$jB%tx=vB!kV+Pikf&%G=BA*h_QA5m>H;jxGl(?8q;t|VPJ52~OMsU{^wS#Ab~CE% zPWUr%&f5)W=XZ3;!`1m~A4X=VQoK7HcQddyU*x#(<%8i=#D~l9P9=Yt#0d6g7h|FDPzT8UFeQ|TeV z?!84H>^R$uFbU$quyF2j`nc6#v5=|D=#SXD=Z4RJ_Id?=(LuXk1=|0)v5cl46WX{Z zA)$v4e{IdKc*07M$2X+cMvse0o;swE$F{+7_HSM%NCNCrCWvtq4G>_G$UM@!*@KZ0 zfrYy5z)kf6#1EP_gzw%9leM3Xzj^<^c z>+_0J-&Fp_WL3nf=mAkbEd;+wl?Uzts5<5#?Z zL*d@9QmAr~IqrJDG0s5pt!Exj_E5+C)@KSwXZ+LVoH2c8kgXaV6tvT7}0ivmIl6Wzp9c{$JQcKA;avSsG&PF2MQqK-`RR~rb)?9=9{ zo$`4Z%pCU9e6;i_(d=AEMTuX_6MerVc3`|2Lef1)h^L3vGs7fC1z{MRs>`flvF_Tz zH5c_AlwUS|w|!hnMn~MA2?qrB7({m8ph5jSly6YPU{I6(=)Vgppr5iV7lwh64*1!h zKz{Lmt%*Qg$P4ADpyfeWPZ9dJ@>J~#0@Tq!)duPm!Kmne(zttfF!>JNC?K=m%aawO zC;b8aP>_8+(g7ulF^yUYBgA1kSQU0E+j6_j);OjO!-IYr(|xkTw(FDGRSt`(%lzyt z`Z2cT9BL)D_IoZ5BtPs)waUNg?@6mY-f`Wt^tc}C>J5a6`OSQL|LPRk>hoWkacZbx z#F_Is{S43_ke4MM_>$$hLW~g!O#Q$+Gx3hTMBMeS0uPKLOsM55po!!g$`7 zio?<-d&v8_I)xjn?Wd2N!YMRKiHh0U{v=} z^@qG{WRRnpy@bO^tv{$&PALc5d*39%$IuJctu`#i)0>m>HbhoQUtSea44prMBnKAO z%{&yrnm_6nGE7puZ3!O{8hvuK4?B~`NXfR0w>jBbo}zBaVMdM*$D3~JbJyzkO$beL zs)8KxQzPYs49}*2*mER9xm>Un2LfSO63bB2_&w78uCCs)^}Gt(clQC7$kNh!$s9M) zkM3)i;X(>c*oEgj=uXRgS?UPO2l)t>qUdu)Uyu2!?mmRHlM<1g$-K>}6oVBUY`l7F zVFzN?LnBk3bxPP_qi_+0YbeIy({2sgaW3z8R|f<>s{&|3UwBO3n7UI!P6F!jJ5!adNyPJo)qsK&Dp_2-gF(wGBo+p^+hl!^()fRVJc zwk5x>13ga!V@mDKTR!Ci`tHfpi>(sEkQZjZglDz43gHzKe9&^31}W#<@-ufx%y2^7 zxx$>5u&Fkszs3mQT_k3lp?xanYXUYuG{O;8d_*me=$XT8MweDJ^rSGbt!$>Evijnk zS~S63B4$W^u@S>gK~Da>%^nCOIbbnTbEPY(Vs&A3sOr<`KYRYvw}qCFS@Aji7rKZI zbFzoufyVI_B^g;cFvUV?3Ko^Fh7$@^NzyHvL6tDOh_a(uFC%BdPn0a8YoP!J6+Z?% z_!~Kv;SV6~j822n(1M+0wVPF+kcc(Qb@EkzLOPyV-?{|aFol?dk8N%R>Ap741iqPI zO)+t$>T%;l1WpzmUb2bM=q@&H391rdDFvPogT?Y9HT73EL-3-0zuf0Q?m@&#nqv!Y zSnJYwwRGnQ*gKP^=Jmm5(bIZ@jpKXUp9g&XW|TD>iAB zmT_%mQ%rXJ*d+BevsI^^=QZ|@gcn2OD+!eo8y+e24kYuC1B`858Y<)!oPu2vMF8mZ znn8!8)L-)pq{CwmRmmL_ShAZrt=(V+Ilr8-d>R%MSh4Z^DNkX!e4US53)(H}>MrNn zU#`J?UcMhTb^b3|Fj+;+lmh=N0h$n$HrD4_Fr52rtZSHz4mFvO3zLxnneEZcqt}NXziF-R)(wTWRtj%?^ZhU5p83NN zTLLHt;B?pdde~58z}o^}1XLHdx3`F)o&Tg5Ab3eGr;ZiiB2Q=CnE1t^Sw%Hsh_s75 z=nm#uhY0GQKW#825iiD@sGxel)!7EOAvQ3$i@2-c5oyt8{5WxN=$-v3@n(Tqm&W-u zMMpHDWSZRtl%T9lVXAf$CY7uCF8&WVH%i7|pBIQ{=X5$=w3UpdjdU3ge+MA}t`QAN zdvm+v+*#h()(C$E5B8BwNAyaA4XlCID@O(r{zudu~(zC<*&H0~a1?m>L*O?V^aplhj?!gC@VfVB-w8HaE@%?`A})%(wz(NndgvpR zwc}lhVWkg6l+fRB#i8S49?S)$Kz_$|f)2J|pEY3C+S%EmPYf@z1xw=gkML;=03^Ye z1caZT-xd8JiGGbfu3xab5p|X5N}T6am{r9M?0#S`#PsR?+~^-Jh?(G1Ey+oQhz0Vq z$|mt^D7?n$S7dAlRkeQlv4{mliL%;rc1W3DV2NO?^&%7`l6m`c1KZ-YY7@g*-@rVp zP}uN?`OpsCP=#n}6*7v$k|7=Ox=Q%?~v@kiZj2%wCEg;UF z*o|!yUwrjv#J|Yn@+qwtR(`-x0nbW!3CeWb&vr_2fosk$mD^5K1BJgpGWn1WX+?sY zi;CP#XDgvZ+NL6E^HMwYeJW5c{w|N0oCqU^sa|YD>*jtXNvokQ)m_5WM5JGthsD|2 z=WBm%E2~;Tq5yJZ!Rehr=$re`q4x+5`{>$Gu=vST^ZxK}%R>|^VXm;96o2LAbK?8F353``TwNF-46prGp zk4`#c%F|9;d3R_zQJ70A&`^@08#WJBa#sIk?*NN5P+!FHuQYg_=S#H;dOC_9tyyN#sr?jE{A-P~cKAKaHKTLk7a@2hUI*r3oRWNm z+dI7)lSF%{YP)ABD8@7eee4Nl_%_1Xs@!^(wjb^9=y6jYWkTU8vtXWsjzAxd`)BN% z;MxjPo)R{s!0YC_hVic*N%b!+H8rMW(VVHng`Y}Xeno_#E5g@%R?rRTJBo)@|NiX> z=n`S@gY^nsZcOgVT z*bE!LT==d&QurPLh|k^qsuPhC+#Uexh88I;%6^0xW1>?`ID;y{FX1*gAK$q^^o3#s z_QCvWnx?MT&9F>Qe_KimSqHjEbB>$4Vm$o>zDo)T0G?Y#rKJF?etG-VXNpJngHON$ z4(xEZCd@cjm;aPcjf*K7`vyUgA}R~9Aa|*2lW)dLo~L9Ce?xstK3F}k;0$4f=3#?E zDOz!gr+%Ei>p-5QaiI;eocH`+x11|6&Qj*?4pt)D-gz=6j?K zNy6)gF@Cr-2!h_DbD7z_{)2H6#KTzvT%Aqnj7JcFzRgz)yOzqfruZB!!Jw8NwR!k# zL6UPwzQFX$j7KWdk#Tg2p0>S)#IH&?n`8;xjFv&^UjZVZ(s2hl!Zu)^&8uVjgQY`={s-EWeg?07lTq63g%6ze|sV^a&OH;SI1G#6nut={oAcoW?#W8 zOHfyY^oV2RJDID&<6eg51Ky=~BfFrF9Ecr!XBXt*?u#ZuOul9S^>xr)NK{0m#sBf< z3yV&Vw|G{p3EO@Jac1 zzY`K_0z@J>Lh^Z`$n@3lfQeiIX}usp?DNmznsWbccl*-Es%JRx5dtInkHZJT_PbsH z8$mtkGq~`5^9Kn>fHeZ8K!DGr@yhas&$_m*IA4q5@bH<{W%_c+X%KG~7f`SnErhZt zc}8LQsU(GHkmRa``zLyfZ|leL5Ga536P$62v%RNMSWoTz?~4wKh4S8D!P}9q~TIoawSu-Q%)b zp)C!)T`%?~)$;Y{vq7Hh`ztw=!2|lG^kKqnlg|n4m{yJIFWiF{MU~ux2TG7HN(cHV zgBeOPwbZD}G%~MvuuMy#WtiE##Q=|ePN`oK8+ULa3oX}94z=PzwMxpxCHpBu3 zuAtt*Fv2D*n3Tf`jcxNwmal$SuWKKAxQ1E&Ow>oE(IBR+BJGK~9J!9VVb988{bU*l z<6-Ki=uuF{`GikY|by-`_@{d^<^?GivgKGp6w$HCJ zWJd6U1=Kd&hQf&xUM_1{Kbdi*qeXTD1+qPK$B3I=D!4CRfF^6urdN*~bSNYxV&=|4 zL-P(kh$mb7s$FsIv8SJtUzU@^Je!r_Azq<;`BV65lNs#C)vF;X(Vt37{GX9sND`>e z{hroeUWBDp-Y0lNU@58?KHiB1$*bu#1|m~!FRu|4%x{273E%)+SplZzr^j~4BY?>z z7yDGf^%-c9UVqxy=#2qX704VA%3}5^-m?Fdsl_qz#`J?c1LD^sC+5SVH(_54h@fT% z%gG9wYy_5BXHOT%BtAf&gnsDqM&fWs(7Jzrm$J7WidaD@&kfCOmV3M@Nl7&!F{yPX zGYiMK+y(Hp@5;(u{duPe8z^pL!3P;sx{@w4hS;B#dPQ>G^Kc7S^OtUb%?lJw6pO!{ zCrpUux?LydJbf=M{pZbjq)0)C*ERSJ>fOMf(b*}9v<`4l2nc8mS~FsB6w86^s{{%O z2zY@@b;^r4N!(f$>b1&ohlG(D5yoprV*#VW>aQJw>ai4Cp5Lj{7?-&U z&KiU|Oe3YR|&$}kIhxTMvbeW7yG#`p4pFg-rBYzd8vsu$+P=ZtKAv{?EL2dtxqmH9O#u8y{A<#q3W_MU(oU0VFjKEbQre*hG32S=X zCBe{Lu$XRCYZmtk^b6GlA}dVsB>TKe(9opWk#CQQ)bNX$ETWE!$~szJqug>RPD9;} zAj|Fz97xP-X%KOgVZWlA%w*fPS25ph(=GBzt0u;y*3(!NoLWyok49$XT8xU$lGH3W zeSJ&$X5??sDDoN(+3{4)sFg`QRn1HY+{apDzE*AjFRQ4Le9%8(^Ps6xD zqd{qGM)_R~=R*sJrvtn6G&}!vxK+l*S#*d8xVF_BJwD$x_bhszsCYxNp{OZMALxf8 zwLB6L_n{=BSgHRdXX_rFp0WTXc?S6SxBtV_e=6f}?tz8zFM0+v{GKc|0$hx-rzjJK zk(oMQ>-8HN3*;K|XZ2^+{*+kEkcK!m6Sxq1eiLspsOG2%t$9RO?!RXl#BggysfAq& zQQxlrrq9R2a@J5aV+8GwS;AhWe@KRNdG9nG{uwPsw$u;B{A&~MyBw_Y!`NY3j%6`0Af05^S=hXEm$9{=oiq7?focXY8*_82KLm#Oj(U(*YL>qFt>I z4}cPWm@=#J0u_b-0&eKtemu{CA7f%-<^ZyAbW}O~?q@knG{Y~#9hvYrPrT_qeVBHm zID)%LnC}=PJ1jgpRrfvZD2H?LYdiM-BA&X1xs)Wv0TA0P@xR@GMW zL1n(PHbE`_JB4vz5} zDah%I#D#e6uNU-wi2dv`R6k_aqc9sPhIvUBz0D}zxe8&Je$<}CR&|dNhbvucbgs_K zo`XErvdkzp<;GY`J=M?(C@sS2d1?bttj$KC)R|8rKgm(=g*y_#h@8Ba?f6k8!H`TW zD;4o+BW2GQr`iSq-Y-?W%RSD9p4igERmg;zMMcDH?QN#Jie`+sk9&663Y~RlATP?J z)P`btt<5K_qQzjSzq%zS-l9k;}U+?6IsFh5Jsl^O8x-BCYXgo+jVmT_9(Az+8ogWTnuAD`TfI=dGK37JuC_n}R z2k(-~w9D@jE!7Th2=BK!B@Oi+ju*Ml5!*aZUJ_#0hCzl^JvZT2%5H|bGZ@@D^UR|a z7mKh`1fkaNjVTd=G9WOUS|jdG$1KQXb*enF-J~tL6BxqrJ4*b+uLZ}Jvo;AM6uYc( zJ_H;LU@0CQ9X)|PJ%obM!YJT8#<&GUIN6;wxBojYHE)gcAb>U4{s7#RFBkIS57;)W zP0!$4P=5r7YoLL*@s{H>Kx&}b>z_XN?jP*+k<)==)A_|F!I(QjmCTe^Yo>puY7%t+ zx!|$WKzh90Kay6+WlC1Z*B1D-_FLc|=R$w=m{>}wXXpr=m4eG|ka=P6@cF+DD z0ski#09U-SybN+QbXf`Xzr9U(;-To~lF)qGZFrW2RLrSE5~1`JA(S)s*V}uuA2_O{ zX7=KEz(@bN>|F+x2krsArt&!D0anJQ{;*4V$yyy;s#tWkNg$KMc$2 zK5ER_`yMxw^DE8|=hM8suucfP-c=J# zJX9pR?o#f)(I8y;;CpV}4;HF?X?FTwnD0&g3^dFajPda_+Hw4-qLG*}`N>i;RUd_{ zM0S{wJaEpT+Q`^HzK4;XfzB>28pb%IV{YPTPZ1}#Sow+Fl41-q;4BoRas%@uFpV=J z^97I*UGma#$}RvLDg#0Bp zEkit4{cnL%&|2`0br=H^6C4iWf2``j!vrA^3H|2b1NdPxp{C+m0fHPsT|&)QvvZ_jKNma%e9tt))dW+y+ip@rQ{7U66Af1+Lv*z^Cl% z`v_c`K=SkHvET&`i`bn(4AoCPh}{h)8UZHDqJgs8tK-dT5Z+j_?b7Ip1`D1>T8q(P4O7f$zf50P^Q0XA7 z=_yq^o#~;_mniZuWOvc?MOe$9+MG-<$ttm~-3bF>*8hSF??5&i5SgBrwz=<50&BZsVdgQckYG0H$zyB9nuujO_|VJfI%)FUYoZw)v7tnbGW2FJ)5ws(=u6d#y!0h-llZ>iM+YsC6eAmio=2r+!w@8!hQ&O4G{R~vw(xy)fH~=VL9cb{hNrH2 zo)u8~_*2%Yu#tIKR^jiw#1B4T1YpwFp}}Z2lHE>={aV}egcCdR+ZJV=5dH0fHA+ib z67oCxWZ)47-O50#u_KWz z_{L$?XcFHOb%NDf7VLGp^+Gql32~H%=J8@Kimf@o+QANMdk_Xy7bOu3)Avju%qCn8 zU~y1?5QTqWm|5sKTywg#02Fpv<>9}HNCXy04|l~O-cvl_;u0Yq3V%bq%rW4h{&E$ z2oHHf;R-l0W~NrUvY-4}T?!KU$W;`)aeU}wUg7uw8?VU<%#MAz&)@%N+y>l@W zS(d--XoqQ4yd_D<3!J3zX?b3a)k$W@4YjadP=6Ik#`=z-&Tp#6J1jJwU_H_+eJRJ-C&AaJF?U4N785PwpxIY~&YiCm(r;>^nb;rG;gSJb zq5cw8J6F`})g%^d8Jda8Wh+hbv)T)_V`oZUsB7Vm`#Hg{bzu%WA3RR*4)aZ{RaJ*; zsmK)Tk?O0&a@XA+@Njz1EppFL^_|krl3F~`N<_n!y`5?W!x0E!O2aLtSOhy37!$!K za3&?w@j!_jHC3lHJ^e({R)p7;t4vfelITssW2NLw;a{!7-F+*WfEIFd@jrW%>S|aV zrJNr~>^Hz^!Cd8^(Ej*YqCISGztAgRTY^6As<#o>H-s|({tQGUn6&YH8%^%WA&h@JLLX|S^(TzPl& z5)Ep!+n6GONR;E4vRYJV%$%{*kN_&E(`+S}dxU{-DH;c>r60V)V zq#5LdTWHC-zTD8~iqa{D{>EHYPjVLei1Y{Q0m?kCIn~JXe&)2Pped&fC)7D2gRJVn zHoH1gpsvAL-o9R_bMQXpE(TH5(dFxCcyz(;^%M$i6ub5jQoMsZ$)97indQ|zbo^N^ z>=7k_+dXe(fOV+SFV(lS^Z-x^lzwNOpr5j)v2n041DL7A#xDPrRswk}5UMJGu8#!# z6ZT?U$PfH;W7JfMQVZvF{~DrzRwC961Dsp&xIfqQk}_OOw8KLV>Q?VJFOC}K$+o+> z*xhVHSPxz59d357Pg;a@d9;ug(Q+duRXQh!xCUw8Pp_9rrxR@VeP^s=E}N5udf*p! zLL8`-%V145_#{CP_(6mm+3d10LJmGdSYi@UiJY$oXEJi4!=y%+@rC7kTsIHWl(Ylf zl7DEe{DJbtjwK};OXemu{TeB84#nEw!1M=!e#7<`7Bnl1`U?LKhl9mwx|{K9!Om=k z)#K>=xZf%*(YYicyQ-Py`f;Cl9i$zi<6OSNVmaEpRELt#e?sPYR??-hAFOCClG%Ek zD;zyLmLm05P_`T>DXne7o5amZ-*<0nZ-@MDe^##h;5Kw20vQCz`Qs`ifbZLD0@O5z z^bN#rN}(DcQ)yiQgU;K)a+$!?crmC1D4$<#r`en;1a3JZalJN#lh#jtqoGBJSGSd$ zOk4jtlJyesX>ss(&&`AlRZN{1@p`u(6Pk)cY$}!8|2`YSV}1~#D1nuL1!;waU59r3 zJxGre6BGZ?JrG}5QM^C9BA6{X<8=yM$ZO)}i86qx&xaUiC!{6XAQ*8nm~vsLAL7PM;vAIw9jV zX%FQklOy>n!%M$rP7x~YTo}b=#-WTVE*fi^STjg$L@p7rG4Z%M z-%%JN-Zpz@y87L;j%zp%5X$k!l-cwR&5tk-qvY-Na%m$Fu1Uc(x8`AduLGa>AEfO7 z6$QNCS()*(olw?6wD!_E2**>N^1E5E7JvuHh3*&VcX$v%CwN^{Xx_XZhdzPY0gXfk zWeAZTD{nSlim@p@Xol%i(j8Pj#gK+xPHilG7vW~(kG!`?!;C2(_>QeNV`>y$Aluq* zb23u)SAM3V`{2)nozdH*w|XMz-qzV~$+t>S=61GsOw#rvCGtpf- zB+K9@W!DaXRrHbLWc~Q{%P-NYntd*Brqf?v8#rg-M^-qn_{JLh-j#q4r}z| z;##M^ZHMr&l*x7p+eo-XEO`{=jy`uCvr#OO23`W|)Z$^rU@ws*&v~Af+A)HU35wby zQinqDmU06z>2`xad1HzweEs`G5LbN%fpC0Wnna6dk!PlMyhv4xWJ2>MVN z`t#}5@Nw=1Ch0_c!6mILWt>i9%W1WtD0 zO9$}Gm$b0&NEEoH#VwUX#`idw%P~WuH+rL37mD#Jikh6kDxtFvx+V5@$GFYIjvfjN z*;iffm*Heb&LrGsA?D|H{p5k5xgDi!V4Q|c()6vbiXpPoc$zd!sqE^>rz_%78mlEv;3^%WX|P75~2y zU_*c~fX~_@u;eJEyo}+0_{eTz&+f~tg5+f>r(6pm@)ZI7Ud|S@N4H5xI3?f)mU50OhRaHogFb1>>*~q!{D_x+w|S? zFD!0ymWsFXRlFtol0HcMxVo$z)fvr<0e2;JLkQQvr*?P}cD1d3Zxyvdgw7FjcY9o8w*%p^m#*G3moeS%Y`zESZvh;eXd2Y0D9tap(iJ`L3+b0*|&VL|&!tHIw zqbxIUJ|v%%(xcw|`VAV+zNIAlWonh)O)=g}Q(7y}ZjDAuN#Go!2J|8J!y>?juf_63 z`-D@%XFvyCEWtEwS1QC`p_SV6oDg&HmVYc@?b(Uz)1Kq`M$+at9nG&`#O+QwmDI7G zio7)<>>VJ1|M{11Mf7o;2=)!-QySy=%cCMSkT3Gbk|9oH zSi$)O?R~_jHoONV0u~LdyvLSeC@NI^)^09;@KSBGDJ!1N|G3Z%#(26xe6n{J;Xo## z@A2Z#uSP!6ZYchjCL9f*<^=47U~{(MT0i^tw;BDoj~(RHdQnp@9J9pCxE6?-PQLm^ zb9|G*R@C13F(2WTk>AMP>r4L*?u-I$=$Ddap72T8tiFPVp|-z167{2%sKlTE$uPVI zQJgx^Ez0Ssr?fkCq7gG&;a~Ad08(M^ices0X z>}>YExgL0)ZcdyC+QaXv83U>llai=sJh?qCRz6l!!5abhSNjFD{U7idQdp}$Mt z7q6Cub`Q!Z8WU!SX`Uch-Tp_bP324TAiY;GBGzg;o~2+F+p}Ef}_i()!bs!wfO71{F+{R33uSzm#D7G!XI#UYWP8{Dqh zlDmoCa~1aZHqVb<-fk`*)vs0%xUm<=cC6)kdu{J08z%x+G9mkYPkrm9$kd-j_j#d~ zpJnl#M!U5I=h^7>L@BKqP@yelQ{hctQ8~iAL2i8OK(ryVk&BHaMW1tek6@O(EL+EQ zsWUqh9Wd+WDx!}2CHbaxYvuFY2&^L0r%TFsAyJi(P+_&alZ$pbx* z2{9knWhfFN`)cbn>ORZPu%St(365zGtcoi^eliT;W-@?lQAfO?6~a2N^-UMxYV$PS z6WVvU`8xy23!I@^%@lV3oqI`Y88iW0OmY9;=bqLOvqv=XdSlqzyq+Jf7aWRO|18Bh zwrp68mT~WlfL%nUf5h)RgSxOPJG*4kd_I-J@{$g^twugc%$V6^JlCGVcTI7h9*=?V zJxKx^x4#ngU}ag+YVmCw@=K9n)gj9}H}7nuht= zB*K1h*yU@EM|z{Rp+%g;(5^g>52e ziSg#Vd~v%Ec80HRC)mA?9PGE-D#FS#&4TvI$ioZMhz^I|#4?lxSEqmNbl~RB;DFv` zRy2|-N3!Z&-MiAx5CbXy3xi?bNbu>s-bc;w(jl(5R}dc72V=xREMz{*a9OVA#mjW`2)N`raeAVf z9!6KF#ln8kPtgw zzc=N-0sl?aU~!L#c;S2eFkCIyE@RP~yoqmhl9zEcemdS%rLO`=bon0YK{@Rs!UE+k z&jKQ?;UneDj?gId!>p2E_+@pKbTyl$_yc5bi2I*ECIy}Qi$d@6(vl{zJXJz2Eun0l zrVaej8A^AC2|D+BuSr(G$p;cvg>I6=AfHC3&K&r{3~8fh6tB0g=LEUm*RQ2p!#pWo z=d&`{g{kT~V-L`an_O*1Y3N1eaQf7fa5N3!!^`*zC08^Qa_RRIC6}Y z;N|;>(!6uHh$nPu{6p_3ZlGA7ds;CDbUBU<;3qC3+Msp$#3$kggNry_WK76kh3>>` zj^=&p3zzs+wPrA!(wW#~^348KaY_2lM6Fe$SzNSa!loyjF$H$PJwpZhgfxxwmw#v< zwsBqwt_iXIw))rPACWcpZvVmovo>FFE?-0mAjo;fPu5!ezjf{j%R1j>m2oJN*aAsh z)K+@tH@qrw@#iY>#fJsA_Gt0G>Y1{ z2@dUgaDFY{A^G;BwZi^`CwY?^?3;0M^pE|rX~Aa_5G_N(L?Ts+H4c0Qc7(6zY^q`v zW?bl-69|;n7jXi-2-^Fm2nh)wo&CU0n}bVo@&tinn$jxpaWdq`N0+D5_dD3sAKdDo zzlqq(L^*BX>Ys$mHb*Rqm{v#3eCd6N$xl;cZ-AYs(K-yL$-JNW_aP!m_iwu)LI6C)YX z^zK$7B*xHDs($-nNHgb~kD zY8g1}@6PVKls*^^9XfCkBL@9E;iK3Zh|EhgZ_s~owU8%sNrNH!?M#!k<0ZvT>7^Yi zhN%d({I-aFU47d=SlqtSGb`}*Sgu^xHG}I2{I6&}M)6V&baYmca?ut3WyrcubzHC$ zx@-y<^^}I7Rv!7w*CEXbVZ4lbbIM4{Gd!N!z5JK!$M+^lpo6+cj$8`2>*l-H@zB=s zsq@oTmlsz9C(bzhbQhMZo@@n1}|B-ykc zr@c_lTG}E9%WP@j292qsDLI=M`%7>?jV{1FunYb&WrVA#pU~o8ftu8oF)e|gVDJA; zmdwp7xj2cn;xi|s{31q)?_+h6B-jy9lm;CwfPbK#aYF}Jb!mRaUd`DO2~F96kV@i2 z9FHef(!+(0%DWYj%H%LlR3KkfiqeE~Z^HQy5h9rYm#8v#Z!+P|Qt2GJ8_a^$x2?N~ zlKJ#nHRhTDMtE!i#SRK|Ev*S5vR?pwiz)E@?Oy)B*;RLjZ;`rNj0_A1Ja8kRp7*pV zJC3v!m*gkx&e1oa;C2sge~yDABKRXE+u7upxZxVliogaFGhm$ELH*HwGNV#|+GO{x zXZ%zvhk%1cC1Tg zw{R3~2qPy&g8wbu)_`EW>|n5eiA0Ca4+4Avv$G5uwIhnJ)b;zHJGDEilyoB5;sn}0 zcU6^?uZ`=TtOosAI`8<^y)+w?Be`WA(N_OAF?e7zYiV=jr1MFV?fz~!l)Q4NRuj<{ z|MNyi)?djx#PDC~s0nnRW_t504IC#4be{1LN5|W?R;gn;YTIPlM>NVQu(C;PLV7}6@E z?942@#y7AxkGNu1S~oKeXS-HD{;DhZF!~T*k%OY;4EiEusssKzG>pQ{z0mmq2N<3o zhx*Z6J9(HfCSy+VrQ9@Zyh7Y+Z$0}w1p+y>;F6_%kfMpzA{I=xve7fQ>hy3i?qAL+ z==5@k+*Ue;yL-_t%P{E+kAsPoOP>RPC|$G|fo}J*MEb`eN2io{P5GnDwJ6AJP()p1 zrS552w?`*GFudo^&?Y|JEX8amev8E*hUD6)YJp?1N!K?(-b{}4Ha?96?Q>QwE0Asg z13i=RKH^xWAU7Fc6)|&kVI)uOu6>1vBqIBr9-j~96x1#>1&pWO=gk!@aSto79 zhc;UJI#$|tvdU5p#Mok(a;%k(I~4O&&^U12?QXRaCNW6hHP=}V&#Jfa*>47EKpkNY zz3Lc6m-vB=Lj@YXr2J3_F0AHL%*h>G%2TK4}*!g;0q3xnxPhJ`?9R6H=>$OwUl^w|I@Y3EHix!2n7CHXuI2b~l#9`FhLS`baT~_HMS%~%Y(Z@7NJ3D6wjb&Mx1r>E++#1dc0 zy-?&hH&ys6!VOPDSy&f+rog!(fPL|SPucJ^>K-gO)f|14;uIEa7 zamB-&e$k2Q>^V?3P@bO5*wMces>kBw#!w7jmb~imP)omy_3cBy{dCFbI{9{~uoHE# zUjC|plAUkJbdLj0@BGCv^c94K*n48&Pi@O@qLW!!%9mT3UriPZ5t2#m-mYh%$LIWP zm}MJY^K|J0H`>?Tq@=6Od_w%J2lSc24;o2>Qe744OF5dx)|-#sdSzJSoq?pkHf;X7 z=^frIsz?}(*5S-AatXAD9TCa^%IlUXSLe+{v~CMzRvHe2~59XNUQ&9 zJPQ8eG=zyd7vST*YcqYeE(>+du?ZkGfHIz9y_Q#> zMrU-7vdy^*iWBD1G(H6-)96~D*D~V`V&_tL8_r$cx6tHIi70BrCyf-!(Bm7vI;vzX z>%)u{`S2A=rItUg`>EQZY=vA)3pl*Dy&t1iDspIr?p2fFcKOYUGD zErxtkt|2!AOg?8UN!{`VzW_DYj+}b0F{B<_fR5}sbJBm#LeI6KYF^v4C30AH~>RIkj zj7KT(l<+&(CY25SFmf10SRqJ8V}Dc)KC~tV{k7*37}Y z(kS-wXU1CnB^ti!VyCwg6JR_!Wwl3z@=aP|_UVI8q>HVpN7|#cc5jddX4f$e-1?B9 zoI0Mn!)@;noWt``qb7@x)gj;AKk(sj+Y*sd4VLCpMK<&`@D{c^9~BTmTgyd#fA$@X zzQm-r{Ni4Wq!NBxc;(<4s=DddNMKg&<X_X^aZsyx4edW3U5~Jym{`T{b~74{)mvVqRVv=wa9(d{_8QLC z-TNOP2l`+_ag45$_o(GcKI08)F+df)+k_vtwm8dLcvfQ2VI?9Z@a=%%+s=RV~3emXA z-@G_@{lehFu*e_BzAyQ#Wm%hL^LhK|Q9hlObtCA*Y1-y-1+HnDwmGN+thfO`zKbPv zJ19{V%A>44ATkkTFcsI0VLBQR0=sti_QiS+bG^Gfhm(N1oPPNIi9CJoZfehjQK!N~>7<`^ff=p-Y^WJawC=U8Ht zOC8Xq#1CwWCI=ic&OU_t&cWb`u14Xt^kC*qE;tfv3Ibf#> zx~4E-4B_L!`Raeo)7)4&ng@z0okqK_qQ)e?C@YCZu|AFM$Mb~XU-%KOL#t1D_O5yE z(MZw&)q?CJf`k%ob59H_M4YUIvIW;zfo&S)9jkH+W-Z z%|sIyBIYxQxt;}-!2xs%HC@7URdHmM&PQ+z#tMQ_Ca@?}%}*4QvB&|ZnA>2PagW#w z$&66TCqFz;FJUh%A>|VsDvJd%;o8u4n9h%2+VoH}`5GT$`T+1Pdbxr48_qZmUP0vL za;XQbRR_!rblc5Ya0P{R>P^ItgGY^oQzSq;`M2oT{zs)ngrhzVAXNUg1HBgsNk>Y1ky|F6%tL#WYSk8 ziu_T&-`w;SnW`IJ#_CD9&9T+6KoH;EvfA&Ww{0})(pf_HM*r0B$Mer&EK>W#J@APM z@DuM}RUkR={%zZ4S+|dta(7uhTog^nvP}AQ+z*!$OP*yH$Hk5F)s@Y%IGGNSbHn1b z3xn(Dt3i=9?Mv?jkc*U=%-ZnzB7D9qciKVSW(~xD4k~b=Z6j{LoQ;Rxnon4~1x0se zX0Y8CBRF6~<3rdeI3-D+GFp@bgP#AJB5iqNNh2WRff(aLnZl}44+UmoF^21(9frhU zLTK+`X?(Ld7w|O zBOvu)@|6SpfK52H%k{xVKb{+`{6db$6uLUHPsV~7W91VOViqG(1g}{e zLUC+h1nZxGhbkt^wyU`6%$Mim^meFsS&1E8AdFAg|r738q3?~6)fe?#Rj8JgVLJutAKJ8w3u|+!@2-7 zCL}P*T^d|-!lmR?#0&^DF`0sITb?2=4zU4-&K2r{_!B#Gc=se0>hSjBAn0%)*o-%cDK&&)Wh9ouxLXQ+8+Jyhg)6J z1}XFG>Sp!Y`D$};QikWlGP`lEx_NFes`BQnkkNw3BFLR(dAHt}HYIi5G~NyPi2zU= zu>yF-n*fj_$f`aMdyHu(B`fbEx)=-wN`}DW-b8v#!Z4T%hvFWFW+2|U_{u7Clj{x9 z4s@eJ>wR|(h1?iQdFl3O9_uR&QB=s#fD9mII4i#Pz`>!!gefHEmn*A{(dtRdp`B@% zW&>g_C{s2pmg(5j$0w6+bP#!?<~z!4Uz zwXzAA5vgR$S-%39w9YU(%PazIHy&0d;0DeJW;%{pIqbeKfz{_312qvji|}ARvBg6U zg;i+ylkrzi^I=IDPA3?0)wGIJASPRJYlV5zfbwt3UpOiDCxGM*x42^F_3fGu2uZ2d zb*%_2XK_3stmDKgM$9n>+Ro@U*9JiON7+MGnfS})lJ#MXzz!=N2`TRjiC>}a!r21q z1m+rX>B2NY<1B!o^P=V60=}ktMp(C5ma&J2kOi(`sA&a=Sz6}1ke{Q;!{5%hcc4?G zSC$t59Hb2$OsM;kYhdi3ftGm`4|KY4IdleigEkcl7N0ewKU2x;M?an$?jQZl3V`@n z{r_M$XTEXMG;MgaEbi7DlTfxn`X$_tD1_a#Qsi=VtGs!x8kQ$jB+9ew>Q=RVt{N0s z6Xa|x#!Ms^*lUc~C~#PXcVx~>bw4&zenL%>zn&{89SCp{~LmzxRzq5~KV_J3db$3wS08Anvj> zBnYKlD140AOBvZ93;Whl{F1rYFY(_=B}Co9N=N00a$J zosCS{x&RuKfMU6jfPfXpZ!|jPK<-9XDME-r8HEU3mI>2SNUf@|`eh{WBnz9NJ-%O#4J8U%9Vv0RC zXPCYgoLYG>ur|1T0getV?j+R9F9*#Tyudgq<>N7i)!gO7i6xh9aFyZhhC3JPJvz5+ zfQ+&bZV=Xr6*4h~rf@&{@uC8nIQ^dmfCy@A4(R`rI=eqF@63v6EtyE~{o9Y|XhJCR z?Bb}nvRPHdNv)DBlk=nE(nc{T@^DrP0C|>)$gFPe&f1-2@kq+)VQ#<&5s~yw0F2Zi z*g%sdTY?#t74DuCvI}OtP>!aIl8oW(129dgx^t}Mr4_uEj;u=a%W99K$8mg4=&AS7 z-UV()Fgic}WW~wX^0^rFpZk&xJ;=-Y`$CAp!4dtcITK=gSyiD#62XVfSp(-gY;voy zH?j#Ndd8o?A7rW=WoE`q8n@)~MduLO`$O>ens<3$F-~oa=Bl9sBXCs%xqJ8SiDT;M z+uwNOjp=l{x3{Ma6I@F(EMwd?Xcy>5KVG`g;os&vv`j5FirMiixo&5K<4h}KZRjxl#1cCIu1p~yHBl~#ow(sGhi+^>MD0Fo&5f-tzRvu&j6IWt7Bi7A!IH~0T z{pd$OVv9{A6WJIPHGHl#03w8tMD&1q&zy6o* zY24wjGE$=91g$w>MOA2_*=3pd*h8aG#{VMW;#XOjcrbW8*chXWItX~m@);6M~eZ* zV8*v_b$m#)_p3uK1ccY9QrtR#pcfEMdBDgkFEH4T6U|Rg&rwC4v_0s5B%HmYKOki> z672&x%@dnPgK~~~!F>i&shbx#?CjIanjuDz#9R-KkU;3*P>In=0F>-EYg|~Fy^f#2;d-{ zgWyuzwpyLiRmVzDuo{-tt`QAwImGAob1%Ir2Yhz@UX~(dt$)bzGbw;=yV&_h(;gIl z@FCo3!I_fTVmxVxHG*Wd8JXdAzLjLv4vxE<*{w)OJ{800CW+(989gqOgtLc%5w_x< z72XP1i%bU^KA1Pbi=Wd=Cdzq_K@>Bl)2V;4vZeZ`em`DFK%@NN$IG~FLH{={z@crM zwgLFK-{g1d;ci<6kv{70M|bd76j@bd<;l}e$~+rY`Jm88#+g7FM2akHB)dD$zg!M( z=hY%ed*A>JjgU2)08Vp$b#eotno?VkL8z&(Mv110lVNU<5{%vp5*g+_Fl_Bfpk7o# zNG{)_DqdDXR_%HDf~F+(pYDotPqsg>DAUboUvT`xfuCVucz~W~nCl!V`Q50;6;p17 zMDUSawr#suEHu3LlrKbjDpRBXRDFM>7i#D~Gbr!m9BqT<2;F9Tz=U?$2) z?X#LFt5hNFLV{-cQ}N-*wl+34Mx)W*-kz!e@zLsQhQs0c^XGSWcW1L1st(+`%|{Di z%%-Og^y4KBY|{65v@l@ApZ%uoh2vOz*|?aP{hy1Yrq#x)_lQ#y^3N%wi{Sf~qCPbJ z=*L-2mQ80Q|Lmz1>)#HC7UBHQvg$9=Ein`&a2(fd`}7_F%yS=&M(hX6QuP|C1GZ+# z4*eyI)EgmAX7@kN4~a!?VoKKOW(betc++4dq#KS!pg9J!ia=Ec%^8OQ9oQaC{9`9dP!G~e+> z$6>%$SDYb_Cb33^$>{sD1F$JLv5J&8nr8T3R!Qr!YL?3@(}eYg9A}tT#^eAKjS?WcR(Tmj{%kQ&C!CUFSwd z)#F@DoHDq-cck=rrpZ?PMB$^1Ewi^z)6i=$7zk;QB1ba`g^XART zWHOu0V7JD%fLRZEJiQ7~KVH%(+8ceF3TPA}?=asICzci6=)`FO8O@*Q=IIO1Ua-z= z@6orL?bJNrdMaB#jxX-bUhEB?I+$p?rwPN3t0%^TOXl!W`-!YNf28Oj&v=AS?*RaU zfCd??FK_&jjO3XRKbkcY(H3BM^hU9fLqipHG2~_7(L(x(@cB&H!-93fpU(tp`~Yq; zly*#af~SWd5;c*fmz`m}m`NW-oJ0#1LTcu$gUPi7oDoa;^A$9leKtyEpwmC47&^g9=xaEa(OR>U{C8BFYj|a;Yf?8@|j#`>& zKIjVo{dghq4b%UF5{4x_Q4v}7063r*w{_b-s*8KeYIl(>>YxHI{pd$JhL!9&2J?A# z*2rj?NGmcGY3HHZFYDc5vs4Q66Gv{;>Zp3xHvz1GHH_C7c0U>%Su@kr4>(x$u(F|D zr;Y@1i-FNSZq9`Saij#(0m;YUO&uj>*y#IE{aZLDjP|+vzK4!HmcuYpmN3S)KI1jK z8F9@JeAui2>1SI92xlBHn^V)4Uk%Sd4%7ES--eS`ZZMtC=P7{>b`(PdZfqymam|=O zczq{d(EN-M?YSQD4Kb=W?wa3FCHK4)?te_b$OY7!~OSN1yMxOR2sy&*T`yFv7@^1 z6vXF#^y65-?omgz9uSiwi-oqNH~Fse1YW5ThPJ1)T`Hz$iYlG#ICt>rJ0 zRYEjBcuXo{fMy&XECgV(Y7!VQ+1V!z_$E|tO!qYVB{0?u$QWP89};~&K}Q}X1oM;? zvN8s4%O1!&&!}FY8$(Ei$wc!oNLVZuoHXjHGdCD3xwFwOsN(z^j;-aOGk|kHQ++XN z_OCcyK+SKllrS>=~;fenosjM|&x3g>lNm|@ZrN^W4s zLx77Nda;I~tq;6&a3z|IH#^S&R? zKd1_;w96FzA5de{G_yLpw;bHB$IDRkiF-e~k!ulY+fcV{+dhxQ(gs;Jp>BgnI7^vm z$Rx|MWt-iel@IoZi+T3Mo7?*Vv@N-N_e}u8kT=|<@Vsu@R+-(3a{3(4WBP`*z$h>W zQPE<6cZ%a)Sd)CFdVIxsjHN&s-(=98opLH0buErc-l;3u3B9~%MhaLr z7s!+xIFaGHj>#YS+>sv%^=H6JnhOlb7MrF~XRl~NuJPV-xirVXCt}1WCFai=wG!px z0f*?(yB@0x?p9uFh}T|KRm0(MZ*OmRcb6SX5&dp#Y+Si=WwBVyW;0o3^5IN1BLj`5 z7r^YtOZq_JZ6^hhr=GUP-rVf2rb=h3eVkNsHb z<%VE6U_|E)RZ5-BSX9&yrZ{UwxR2|LB*EBPaOlHT2RLubs+<&v^GL2dflF4~&-L1I zW-cVlgHB9SpG%44vQQYGk!cPvvj{P~8(y@{)@^9jnBmNxs*kLOtiFzWwn z(*N5wOl!HfsCMciWTB_~^kW@RzHVjFJ`d=*4PjP?Wpmcj&`hKdSvGQeF1PZ0uNf|v z*%JvMv;t5Q07Sh+UR~Uuu};?U7gxwPC?uoOhLPj>nB0TNJa?0-nNY{WG+u;(55r5< zoA`=f5H*N1$L8}`BOqe{dh-cUQJ_@m#ppmH=>xyVqhLrwa8exnrwonxFqX^Zd_Fh& zIr;+CsKI$DcSJ3nkV$c221l;Znj!Rn^&+xP1hxT2>Xng<7lG zD$mnaIFD1Nlu&OyXXS{}l{8b9_8+T;=wk1ey?NsIKHQRwZJ?Pj9Y-&Gksr?NBTTQ!LR8H0R1@Q zS#u2gjyBUgJCYvl@bg+>QT3tcHYZP60N~gHG+tRXxrKZ-v*}H%epF)H=V&LP>588?&(ddyWb8LzJyu+$G~8(yl2 zGaOFFaPMeR#9nP&0_jITp7YcC$n^gvdr(&o7Wt%Zn^v-{*Z=9q;iGB8yl$7xi3g_h zx?R+*768uDo|=hdnKX5nE!)YU-5FH-i$T-KW8DAXW<}lZNhME00F)qc%=A@D-c+0< zgs@yL5gHXmfu}Qv{oqe2^oOJ*3~c}vXTyubP@cXJOGZ;F zN$VyF8IPsbA#zo`#>i&Ms-hI9V6rOr!I_ab9|9<{GJwd*3k&q~F>o6z=x&3-U@#bL zZf@pze*5-qEtdE$kefGeHchj;yQ?(-{YH2Ra0U&1SFfeskA9r?Cvwc^!+3Y66#RW} zmajnj{vKbVmUM4ZR2aZ)%Vs-`3WfW=F8+N~ox5Kf{djp(;}jD=DwgF#nv@Vw#{85EH zR|L4Tx)5W2Ap6d&c7yEe8R-pzHGrlK^m7=f-S-giltwLs_*|HWW#srF%LC;oBV1$j zYO$7-WslMwA}7;|=ocj4akAQc%_~8ibpeh6-@=U@`bKV;5NB45dx3?g0R3~P5eH}d zXhrS>j>@VYta9jHau7sx0l2Hrf6G{e$Dn{tyEds5ccNH zqgj2T``m2V?#`Nd-JVrnicCa;?1ykClsmJ*LB!Lt2f&m6viv^)i0~>l>6?gD0~mes zvJ|IAeGKbxT8My6LmJag%2B#OS|vu&iVEF$X&{5tbeR3}FZp~;^5Vhe4v@$kPqe)t zYB|8?6}1uORL=WP8Z_L*X_BTuap$+;rz1EAhYXWk*R=xuEUF1&7NT^OKh-xbmrM51 zHC+zfC>UoJ+%U?^2G`4!m!c&iA!{@=Nt?)JqgtR?3H#eu#>F(~X ztTy2451X5tH*VZeA7IUW^fS>}?sY`_7TA8gjKgU9vyq_@<@ZRU=isl8)^*hHqjzqq zgy6Y`{^=97CYFTWh%aOGqaQCxk`iY>q(}@M<+P)c@fq;sPhiwE3hsBeAe^dpocz!L z-Gp&Wp@rNBGj`cJ$;@M_`;}c}O)%u8;f+i`J{i#!4x826g_Pn=6wdr>M46mX0P@D? zcrFZY@f;(vXB1<*%%I^2)zqa;8w6_yA&22+1x_m19F>7`UXgf>il2ZL!rXRTIOXi< z}Kx0QhAN4CnUj-MO@F6Vc!p*Ii4RF|_=r*o0 zuS~DigEEFe{~2n>W#XO#R#g&eDmQgS{a9U-<`ayI0OR%C4a08OLI%!4Qbp$eil(5( ztc<@@R^5i9e>HQ+rW#RQRO4OD%;7$z?WNRyEg#n#|x+d5G)uD zHpp)J|FX><*44dwP)ptu|NF6S@Rvy&BV02UwiC=!Vu~*y5&&;3J=?OC+Qvy>(q zs}FPEdGh{K!0stSCUZmiZ%;{hox<2Y?=F3q`7Me<$vA+_4A3mAWELhn`}i0>r9Osc zI35~^3iAO(=C)siO$@jjnG~kdo3>D2Gtm84Pu8%xfkgY}2L3N#O`xT09n9az9BPDv zuuk=%GqX{+!r_5YIcVnKZVcm%3|tsNv&O*&N7j@KT9e8g0oUF%-I!cLzXjnY1N4k~ zVIJrtu&$j+v+3NSbn4r6>w5Iha%g#{;!ZrjK!Rgauz8gv)IC0K8e5I7Neasz%uQtu{+)W~@>@!}F+={_7hIs%b zA4v$8BKQj8x-cuy^O$s2xef=H3!WUdj1%g!?j?Zw@ti>aRr>#vltUiV{k!S^drNt+ zD0UZl-G(fae$Dn{jp$a2ENj|uZ&H7~Q%{#CMG&i-_Rik&_U>|C2aP+<$pK(hl${HUV(-3vVZG4fN8+rs=RK3N>!^9oZ(XHvU5f1M(FD z(!#V@f=f|PZHp?{jj(^Lv(h(WA@nKHOzstO-G2lGOFAd?XY zIanIg=Fw;b|2Yjrm9Y+h9_)3z7dkfRR~Bm8Ho6}jx7chp<1B!q!Dzw8sGb5$_uN}l zFO0*MiJX18g|ir7f=pWxYBwK^M#JIotFOM&+reP^A%q(@Zsd8szrWu!&1^O^f+Tng zxJqSNE*6XaS=o=5I;i&j>%Kq9Y;orIjJkLyc4PM20W~rsjX%MdR`S!wGn)C4l;Rpk z8PNTz=*L-!x03=s(be9e<9}QS5S1$O#r|XY_LD6D7>98atj}gM73GACprN0zpC`9} zGQV3lLDrXNvN=aBrqh#kx)~YQNYM!R;KhpN8D|)dO@05DQ5`XaYlBhpzRaL1KS%(= z@`tn67Q^(g3gCi-xSka5oG?-+d^JHEVOG14Clz~n;b=9^HWS5?HCzZ$d|y^&l$cxX zOD6azmf7Kl92359rYs4iS5{?wjC&PM5CZX@A!RIr(F?+abkv*-kS(jyI)Ip&*B=!k zR7Bf!9$-E>zcr>8Mk3$T%*>v`{>C^ABu<>J7=eD%+++%A+~mR04BwLCy4txV$aE^; zzF^K2?gf0H*5N$a%~%UWWwLPmpc8^H$eH0{u`q`{nM}~q(T{#Sr=%rNUeT`D0Ho;u z(hmt{E~k0+DKg9i_cHL-rexpU_(Uc5M+PN&l;7g2D5 zkW1o==JRD!Uq^%@WbiBzq`#T!ZAzw8#l+z9tKkL^SfFk;+l2zqr z)6gS*2S7j0QiAO6^mXc6(Zc`w&o$p0x{h;zf&R^HcuJnCc}H3Doi;W{KS!L)%4NHMU^UHWw^`R$g!mz-ife3XlCENsC+`+&MYtB-z92w3w z5GtM)hGC80Fn=5{DA@NLG^dgf$QHI02yzPb0kFpv2kn}Y4+evcjg7l^?{Wgje3$L*?a5@azrT;Xl0`L*WN7aM z(2tiisP@}SM-3pQ91?B4^4nc>vyB#^CDtF{E#G|^z!$TlJqKKUG>Sld0iYi*dzu`* zccOQ3s`+xwRserXO1gyR8#>Jo(XHmR2bYM!KIXKCDIu&- z$%~swAHEm>3u0ryWsqWXw=i(ey{I5-3)$xAVQbZgxl|08ijy4mE!AcvC@aTE_sFW) z4le*L3BacTr!T7=2F#Q)0_yXo>`;4eZtVdQ-n+{f{-aFCfO91^b=GMUW7?fqk!K<+ELBmip3w`*ivOgjLyv9HRN69LAu5H_E*RF}kbUIaGB~#il?hXn9^eRC8cyMk>&fL{rfzEdVeCj7SUUJX3>>qoy1f2WgxQeAYyPunO>H zOz6xYvSEq@a}!K5;K6174eA7}bHdAo_fyn4nxNnhS!RRnEyMYDkB{L|qam|W8OAN;xztKZ7pfi)UilWeV zR8Ykk&<73 zOhlw^!(=Ht?O-BWV$tl3z%^W7*w~6=>4G1FuK*W~6@HZPF01{!XdmIpK`QDAF6I&}77L9P;X_~!&xmuf zemBbv8TKynS^k-|XANN)AIN>E<^>!W<0_~Pz~<)Wa=F~w+l%fbo12>#E?k&QCbQX0 z^CoS};BPd|_dO4$A1~8Gc-1k{+*3?G6b%kySfQS?yHf-Iis_J=AWv>MWSUB?QzJ3_i<};vA=H6a`IoFKoi) z1R$Y8#A>F@^Ma_Vs;VmE4a?bu0V28H%Ubh>Yi|-H6ET}cglG?odGh(LQVuj_)$$7q z!1&J?sy=2IvYXI@QskY1W1Z6BaL9}v#K+nQ%qy}kJZltol3zCZ~ z=DM(@gseI|v%U}~ho(`Qqcl_w#3>_TsiWv+_)}(jxfKAFGsYco7x!UPKTZ_xmsR`U z10@i&008hO1JQ$@rge62S?z^k-DbV|e?Oio@>VB+aCfhM@6Pm3x26xK$0PVKufvD; zXMegi`Rw6hvTTby%kx*IJhg1Id&|M2cGyU+WPif{pOp97)oP!R3&<-nQBdX_4u>GS zESF2Bp_FAg91aa+W2g^I@{rXgUBu_cDhXfBfg&deo}$E^$DGdLm(liO^9j;P95bkW zG(n9T0QfM~OHlf6Pk~1r;FsxaHnV3)SHQ|y@|5FDFM-V#~**}jra6rH*VZe^dD^&Y)veymejIJ$m>TxUY220YE6!8?oCtClo&5qVsdSs zWo+8cB+VK&fKmtO?@J5*lRF+6LSB{q=*LT!CP$^WOcHG{E(6LR74cukRKSN@9o4vX ze2JfbO(p38puq&7VZ_SH8ZhGf96xb%4$YI484L3cWVJwmS4IHykp_Q1|92)g1^7`?HV(~pgwFCQ}>ybp#=$cm`gw0dyuf#(5AM7$cgpMbem>{g|zw{Oc3YSh+y zp{lCQ&CT82U6oFf0~WuCESF1F0SY1P?Ck9C?`tK%AdlXXfg|L8^y4K6r)dFmebj&| z9bPPEf8Z^}`SKpz`(*_6&==;G|sfjTJp~xUcQ(FO>B5W=jQ>R0<%SoCX7%Aw0{&aU~M?><_B3d ztwIdVGC@L0EavN&BX24Ss;>fNe8yf4C8}wf#bSYcPhSJ~S5W&|x(6#HDsySXF`2I< zWO2byZlf+`N-4YmcrkOPq~#Mcv6x06`{?Jze+`G7?_OplFmNAr@kJKl0eU9IYrbu| z1WfkAw;q?BxRHX(45-x^ZiT6MF-4B)|Hha)+LFmFCcK_aYlu&7*(t#UUfg5u_b&dx ze)QwSlNN9POPW7Vpnv^O(}WpLk;#FFmd6u@@4iCAydUnGWu}V|f2C;}#i?;|u?&>#&!2{C zr`KHrHb_F5Wu`+L2%@DFJvQy$=0#-+LMD6VNZ2oLqrVYd55WDAws0pmr(oP5Zb~Ky zWrxGz#>U3p-rk)%clc#EyzzK^{rdI2y*()0@_ocj8~SxsRl!@UAN_bK9xJk1?v>8E zrZ@EFSEhQTqN)HB5aCugF4Tk5= zTO?bsGH}^ZdlAyvXH_C2=g3&|9b`6e+h0E|dUc+ty+&mj?6En&@2t(2J z%&ndLQ64zvMh$!~<`eE)LbPrpe<>sn#mp%qsjq+1&=Vi4U8{T*(0QOV7Gw*Xo0~8_ zW|O zY_}cGLfNz;>;j}LUe#4=K#B3NjK2NdId^6=b)J~J2MzN%5DrC|bgJ>J-Msz6}nR|bBJgaC|MOK1z z$!IR&@NoIyy+O=zHcrcw#mAl5B zwfYify5BOmrs~(LV>dmt1(ii2n zc9_%j3!@)rsSLnBbf|TC*!@t5{7|1H6FMI0Gf(1{JXEYKHA??0-kTWxXM-j~B=O98 z=8Sl2R>Xo3Z3LRktY_n$;$vk#2Gaw}Z3GL7rQ^_@C4|#L^XWBgRjb69Z zp9_bNJ`F&aYoy-!U8d8S`$qlA`fq1aIfM180cBX&I0lK4PAZS zE_cG94tc8rKt0Q+AJ2-$X41;M4xc_)?9Q7ncbD&68-45Q=<>KMa>+A^2Dyr1H$f(g z=Cg;3zucL9cyD%lx1KKBOr*?TP5xPyXJOvv_m{(sydGqevTd_WL(-6I)Y`VWKFalp zBOyDuhxzAMp$5PZ?PxR_4u={r=tF$DTp}v)c}g_jGr0ywO{SsNSh*U>M8mD|aTG&B zQNi3XEo_! zJrIDE01zRz2==bVY8u0tVBKuB9DI1cb#WaT#*7!VcZ2&g$bx=hyoKuo-V0u0&Jvz? z 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

Tg1ofHcY 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%0D*HXxB#S%=eisgidpvuHvF?fv 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⩔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

JN5R2A>$4cv#t$-r^sp-HU=RWyys$Z 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

-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
    ^ebuUd)@H-tyI_>oO}hjtl*GnTsmR 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 QBm> Date: Wed, 25 Nov 2015 22:31:23 +0100 Subject: [PATCH 58/77] glTF: add missing attribute buffer for text streams. --- code/glTFImporter.h | 1 + 1 file changed, 1 insertion(+) diff --git a/code/glTFImporter.h b/code/glTFImporter.h index 10033649b..dc113c003 100644 --- a/code/glTFImporter.h +++ b/code/glTFImporter.h @@ -56,6 +56,7 @@ protected: private: aiScene *m_scene; + std::vector m_buffer; }; } // Namespace assimp From 64a020965f0337a495210f33b9ed31984f91da74 Mon Sep 17 00:00:00 2001 From: Otger Date: Thu, 26 Nov 2015 02:33:39 +0100 Subject: [PATCH 59/77] Added RapidJSON to contrib --- .../rapidjson/include/rapidjson/allocators.h | 261 ++ .../rapidjson/include/rapidjson/document.h | 2114 +++++++++++++++++ .../include/rapidjson/encodedstream.h | 261 ++ .../rapidjson/include/rapidjson/encodings.h | 625 +++++ .../rapidjson/include/rapidjson/error/en.h | 65 + .../rapidjson/include/rapidjson/error/error.h | 146 ++ .../include/rapidjson/filereadstream.h | 88 + .../include/rapidjson/filewritestream.h | 95 + .../include/rapidjson/internal/biginteger.h | 290 +++ .../include/rapidjson/internal/diyfp.h | 248 ++ .../include/rapidjson/internal/dtoa.h | 217 ++ .../include/rapidjson/internal/ieee754.h | 77 + .../include/rapidjson/internal/itoa.h | 304 +++ .../include/rapidjson/internal/meta.h | 181 ++ .../include/rapidjson/internal/pow10.h | 55 + .../include/rapidjson/internal/stack.h | 196 ++ .../include/rapidjson/internal/strfunc.h | 39 + .../include/rapidjson/internal/strtod.h | 270 +++ .../include/rapidjson/internal/swap.h | 37 + .../include/rapidjson/memorybuffer.h | 70 + .../include/rapidjson/memorystream.h | 61 + .../include/rapidjson/msinttypes/inttypes.h | 316 +++ .../include/rapidjson/msinttypes/stdint.h | 300 +++ contrib/rapidjson/include/rapidjson/pointer.h | 1313 ++++++++++ .../include/rapidjson/prettywriter.h | 207 ++ .../rapidjson/include/rapidjson/rapidjson.h | 654 +++++ contrib/rapidjson/include/rapidjson/reader.h | 1510 ++++++++++++ .../include/rapidjson/stringbuffer.h | 93 + contrib/rapidjson/include/rapidjson/writer.h | 395 +++ contrib/rapidjson/license.txt | 57 + contrib/rapidjson/readme.md | 129 + 31 files changed, 10674 insertions(+) create mode 100644 contrib/rapidjson/include/rapidjson/allocators.h create mode 100644 contrib/rapidjson/include/rapidjson/document.h create mode 100644 contrib/rapidjson/include/rapidjson/encodedstream.h create mode 100644 contrib/rapidjson/include/rapidjson/encodings.h create mode 100644 contrib/rapidjson/include/rapidjson/error/en.h create mode 100644 contrib/rapidjson/include/rapidjson/error/error.h create mode 100644 contrib/rapidjson/include/rapidjson/filereadstream.h create mode 100644 contrib/rapidjson/include/rapidjson/filewritestream.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/biginteger.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/diyfp.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/dtoa.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/ieee754.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/itoa.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/meta.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/pow10.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/stack.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/strfunc.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/strtod.h create mode 100644 contrib/rapidjson/include/rapidjson/internal/swap.h create mode 100644 contrib/rapidjson/include/rapidjson/memorybuffer.h create mode 100644 contrib/rapidjson/include/rapidjson/memorystream.h create mode 100644 contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h create mode 100644 contrib/rapidjson/include/rapidjson/msinttypes/stdint.h create mode 100644 contrib/rapidjson/include/rapidjson/pointer.h create mode 100644 contrib/rapidjson/include/rapidjson/prettywriter.h create mode 100644 contrib/rapidjson/include/rapidjson/rapidjson.h create mode 100644 contrib/rapidjson/include/rapidjson/reader.h create mode 100644 contrib/rapidjson/include/rapidjson/stringbuffer.h create mode 100644 contrib/rapidjson/include/rapidjson/writer.h create mode 100644 contrib/rapidjson/license.txt create mode 100644 contrib/rapidjson/readme.md diff --git a/contrib/rapidjson/include/rapidjson/allocators.h b/contrib/rapidjson/include/rapidjson/allocators.h new file mode 100644 index 000000000..24e6044b3 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/allocators.h @@ -0,0 +1,261 @@ +// 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 +// 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_ALLOCATORS_H_ +#define RAPIDJSON_ALLOCATORS_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \note implements Allocator concept +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return std::malloc(size); + else + return NULL; // standardize to returning NULL. + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + std::free(originalPtr); + return NULL; + } + return std::realloc(originalPtr, newSize); + } + static void Free(void *ptr) { std::free(ptr); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \note implements Allocator concept +*/ +template +class MemoryPoolAllocator { +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \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) + { + RAPIDJSON_ASSERT(buffer != 0); + RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); + chunkHead_ = reinterpret_cast(buffer); + chunkHead_->capacity = size - sizeof(ChunkHeader); + chunkHead_->size = 0; + chunkHead_->next = 0; + } + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() { + Clear(); + RAPIDJSON_DELETE(ownBaseAllocator_); + } + + //! Deallocates all memory chunks, excluding the user-supplied buffer. + void Clear() { + while (chunkHead_ && chunkHead_ != userBuffer_) { + ChunkHeader* next = chunkHead_->next; + baseAllocator_->Free(chunkHead_); + chunkHead_ = next; + } + if (chunkHead_ && chunkHead_ == userBuffer_) + chunkHead_->size = 0; // Clear user buffer + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const { + size_t capacity = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const { + size_t size = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); + if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) + AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); + + void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; + chunkHead_->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + if (newSize == 0) + return NULL; + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == (char *)(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { + size_t increment = static_cast(newSize - originalSize); + increment = RAPIDJSON_ALIGN(increment); + if (chunkHead_->size + increment <= chunkHead_->capacity) { + chunkHead_->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + void* newBuffer = Malloc(newSize); + RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) { (void)ptr; } // Do nothing + +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. + */ + void AddChunk(size_t capacity) { + if (!baseAllocator_) + ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); + ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity)); + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + } + + static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. + + //! 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. + }; + + 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. +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/contrib/rapidjson/include/rapidjson/document.h b/contrib/rapidjson/include/rapidjson/document.h new file mode 100644 index 000000000..8c76faf54 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/document.h @@ -0,0 +1,2114 @@ +// 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 +// 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_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +/*! \file document.h */ + +#include "reader.h" +#include "internal/meta.h" +#include "internal/strfunc.h" +#include // placement new + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif // RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include // std::iterator, std::random_access_iterator_tag +#endif + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template +class GenericValue; + +template +class GenericDocument; + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template +struct GenericMember { + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template +class GenericMemberIterator + : public std::iterator >::Type> { + + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef std::iterator BaseType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator NonConstIterator; + + //! Pointer to (const) GenericMember + typedef typename BaseType::pointer Pointer; + //! Reference to (const) GenericMember + typedef typename BaseType::reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef typename BaseType::difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; } + bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; } + bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; } + bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; } + bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; } + bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; } + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template +struct GenericMemberIterator; + +//! non-const GenericMemberIterator +template +struct GenericMemberIterator { + //! use plain pointer as iterator type + typedef GenericMember* Iterator; +}; +//! const GenericMemberIterator +template +struct GenericMemberIterator { + //! use plain const pointer as iterator type + typedef const GenericMember* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ + template + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ + explicit GenericStringRef(const CharType* str) + : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); } + + //! Create constant string reference from pointer and length + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ + GenericStringRef(const CharType* str, SizeType len) + : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); } + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + //! Disallow copy-assignment + GenericStringRef operator=(const GenericStringRef&); + //! Disallow construction from non-const array + template + GenericStringRef(CharType (&str)[N]) /* = delete */; +}; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template +inline GenericStringRef StringRef(const CharType* str) { + return GenericStringRef(str, internal::StrLen(str)); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template +inline GenericStringRef StringRef(const CharType* str, size_t length) { + return GenericStringRef(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template +inline GenericStringRef StringRef(const std::basic_string& str) { + return GenericStringRef(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template struct IsGenericValueImpl::Type, typename Void::Type> + : IsBaseOf, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template struct IsGenericValue : IsGenericValueImpl::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +template > +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) { + rhs.flags_ = kNullFlag; // give up contents + } +#endif + +private: + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template + GenericValue(GenericDocument&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template + GenericValue& operator=(GenericDocument&& rhs); +#endif + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { + static const unsigned defaultFlags[7] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + flags_ = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \see CopyFrom() + */ + template< typename SourceAllocator > + GenericValue(const GenericValue& rhs, Allocator & allocator); + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_(), flags_(b ? kTrueFlag : kFalseFlag) { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) { + data_.n.i64 = i; + if (i >= 0) + flags_ |= kUintFlag | kUint64Flag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) { + data_.n.u64 = u; + if (!(u & 0x80000000)) + flags_ |= kIntFlag | kInt64Flag; + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) { + data_.n.i64 = i64; + if (i64 >= 0) { + flags_ |= kNumberUint64Flag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + flags_ |= kUintFlag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + else if (i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) { + data_.n.u64 = u64; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + flags_ |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + flags_ |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + switch(flags_) { + case kArrayFlag: + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(data_.a.elements); + break; + + case kObjectFlag: + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(data_.o.members); + break; + + case kCopyStringFlag: + Allocator::Free(const_cast(data_.s.str)); + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + RawAssign(rhs); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + */ + template + GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator) { + RAPIDJSON_ASSERT((void*)this != (void const*)&rhs); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Linear time complexity (number of all values in the subtree and total lengths of all strings). + */ + template + bool operator==(const GenericValue& rhs) const { + typedef GenericValue RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + 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) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + return data_.n.u64 == rhs.data_.n.u64; + + default: // kTrueType, kFalseType, kNullType + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template + bool operator!=(const GenericValue& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} + + //!@name Type + //@{ + + Type GetType() const { return static_cast(flags_ & kTypeMask); } + bool IsNull() const { return flags_ == kNullFlag; } + bool IsFalse() const { return flags_ == kFalseFlag; } + bool IsTrue() const { return flags_ == kTrueFlag; } + bool IsBool() const { return (flags_ & kBoolFlag) != 0; } + bool IsObject() const { return flags_ == kObjectFlag; } + bool IsArray() const { return flags_ == kArrayFlag; } + bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } + bool IsInt() const { return (flags_ & kIntFlag) != 0; } + bool IsUint() const { return (flags_ & kUintFlag) != 0; } + bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } + bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } + bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } + bool IsString() const { return (flags_ & kStringFlag) != 0; } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template + GenericValue& operator[](const GenericValue& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + static GenericValue NullValue; + return NullValue; + } + } + template + const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string& name) const { return FindMember(name) != MemberEnd(); } +#endif + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template + bool HasMember(const GenericValue& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template + 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; + } + template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } + +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string& name) { return FindMember(StringRef(name)); } + ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(StringRef(name)); } +#endif + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + + Object& o = data_.o; + if (o.size >= o.capacity) { + if (o.capacity == 0) { + o.capacity = kDefaultObjectCapacity; + o.members = reinterpret_cast(allocator.Malloc(o.capacity * sizeof(Member))); + } + else { + SizeType oldCapacity = o.capacity; + o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 + o.members = reinterpret_cast(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member))); + } + } + o.members[o.size].name.RawAssign(name); + o.members[o.size].value.RawAssign(value); + o.size++; + return *this; + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(GenericValue& name, T value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template + bool RemoveMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(data_.o.members != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + + MemberIterator last(data_.o.members + (data_.o.size - 1)); + if (data_.o.size > 1 && m != last) { + // Move the last one to this place + *m = *last; + } + else { + // Only one left, just destroy + m->~Member(); + } + --data_.o.size; + return m; + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(data_.o.members != 0); + 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(&*pos, &*last, (MemberEnd() - last) * sizeof(Member)); + data_.o.size -= (last - first); + return pos; + } + + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template + bool EraseMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + for (SizeType i = 0; i < data_.a.size; ++i) + data_.a.elements[i].~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return data_.a.elements[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + data_.a.elements[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + data_.a.elements[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(data_.a.elements != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(pos, last, (End() - last) * sizeof(GenericValue)); + data_.a.size -= (last - first); + return pos; + } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; } + + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); } + + //! 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 ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + + //! 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. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } +#endif + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (!handler.StartObject()) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0)) + return false; + if (!m->value.Accept(handler)) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (!handler.StartArray()) + return false; + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + if (!v->Accept(handler)) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else if (IsUint64()) return handler.Uint64(data_.n.u64); + else return handler.Double(data_.n.d); + } + } + +private: + template friend class GenericValue; + template friend class GenericDocument; + + enum { + kBoolFlag = 0x100, + kNumberFlag = 0x200, + kIntFlag = 0x400, + kUintFlag = 0x800, + kInt64Flag = 0x1000, + kUint64Flag = 0x2000, + kDoubleFlag = 0x4000, + kStringFlag = 0x100000, + kCopyFlag = 0x200000, + kInlineStrFlag = 0x400000, + + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler + }; + + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; + + struct String { + const Ch* str; + SizeType length; + unsigned hashcode; //!< reserved + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode + // inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); } + inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; +#else + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct Object { + Member* members; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct Array { + GenericValue* elements; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + Object o; + Array a; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + flags_ = kArrayFlag; + if (count) { + data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue)); + std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); + } + else + data_.a.elements = NULL; + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + flags_ = kObjectFlag; + if (count) { + data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member)); + std::memcpy(data_.o.members, members, count * sizeof(Member)); + } + else + data_.o.members = NULL; + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + flags_ = kConstStringFlag; + data_.s.str = s; + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = NULL; + if(ShortString::Usable(s.length)) { + flags_ = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + flags_ = kCopyStringFlag; + data_.s.length = s.length; + str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch)); + data_.s.str = str; + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + flags_ = rhs.flags_; + rhs.flags_ = kNullFlag; + } + + template + bool StringEqual(const GenericValue& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; + unsigned flags_; +}; + +//! GenericValue with UTF8 encoding +typedef GenericValue > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \tparam StackAllocator Allocator for allocating memory for stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. +*/ +template , typename StackAllocator = CrtAllocator> +class GenericDocument : public GenericValue { +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. + + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //! Exchange the contents of this document with those of another. + /*! + \param other Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + GenericReader reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + template friend class GenericReader; // for parsing + template friend class GenericValue; // for deep copying + + // Implementation of Handler + bool Null() { new (stack_.template Push()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } + +private: + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument > Document; + +// defined here due to the dependency on GenericDocument +template +template +inline +GenericValue::GenericValue(const GenericValue& rhs, Allocator& allocator) +{ + switch (rhs.GetType()) { + case kObjectType: + case kArrayType: { // perform deep copy via SAX Handler + GenericDocument d(&allocator); + rhs.Accept(d); + RawAssign(*d.stack_.template Pop(1)); + } + break; + case kStringType: + if (rhs.flags_ == kConstStringFlag) { + flags_ = rhs.flags_; + data_ = *reinterpret_cast(&rhs.data_); + } else { + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + } + break; + default: // kNumberType, kTrueType, kFalseType, kNullType + flags_ = rhs.flags_; + data_ = *reinterpret_cast(&rhs.data_); + break; + } +} + +RAPIDJSON_NAMESPACE_END + +#if defined(_MSC_VER) || defined(__GNUC__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/contrib/rapidjson/include/rapidjson/encodedstream.h b/contrib/rapidjson/include/rapidjson/encodedstream.h new file mode 100644 index 000000000..fd3bfaf13 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/encodedstream.h @@ -0,0 +1,261 @@ +// 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 +// 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_ENCODEDSTREAM_H_ +#define RAPIDJSON_ENCODEDSTREAM_H_ + +#include "rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Input byte stream wrapper with a statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. +*/ +template +class EncodedInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); + + InputByteStream& is_; + Ch current_; +}; + +//! Output byte stream wrapper with statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileWriteStream. +*/ +template +class EncodedOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } + + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); + + OutputByteStream& os_; +}; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + +//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. +*/ +template +class AutoUTFInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = (const unsigned char *)is_->Peek4(); + if (!c) + return; + + unsigned bom = static_cast(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; +}; + +//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for writing. + \tparam InputByteStream type of output byte stream to be wrapped. +*/ +template +class AutoUTFOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } + + typedef void (*PutFunc)(OutputByteStream&, Ch); + + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; +}; + +#undef RAPIDJSON_ENCODINGS_FUNC + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/contrib/rapidjson/include/rapidjson/encodings.h b/contrib/rapidjson/include/rapidjson/encodings.h new file mode 100644 index 000000000..90b46ed32 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/encodings.h @@ -0,0 +1,625 @@ +// 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 +// 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_ENCODINGS_H_ +#define RAPIDJSON_ENCODINGS_H_ + +#include "rapidjson.h" + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(overflow) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template + static void Put(OutputByteStream& os, Ch c); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept +*/ +template +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { +#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu) +#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = (unsigned char)c; + return true; + } + + unsigned char type = GetRange((unsigned char)c); + *codepoint = (0xFF >> type) & (unsigned char)c; + bool result = true; + switch (type) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + template + static bool Validate(InputStream& is, OutputStream& os) { +#define COPY() os.Put(c = is.Take()) +#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + Ch c; + COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange((unsigned char)c)) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + Ch c = Take(is); + if ((unsigned char)c != 0xEFu) return c; + c = is.Take(); + if ((unsigned char)c != 0xBBu) return c; + c = is.Take(); + if ((unsigned char)c != 0xBFu) return c; + c = is.Take(); + return c; + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return is.Take(); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu); + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. +*/ +template +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast((v >> 10) | 0xD800)); + os.Put((v & 0x3FF) | 0xDC00); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = c; + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (c & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (c & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + Ch c; + os.Put(c = is.Take()); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } +}; + +//! UTF-16 little endian encoding. +template +struct UTF16LE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned short)c == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take(); + c |= (unsigned char)is.Take() << 8; + return c; + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFFu); os.Put(0xFEu); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(c & 0xFFu); + os.Put((c >> 8) & 0xFFu); + } +}; + +//! UTF-16 big endian encoding. +template +struct UTF16BE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned short)c == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take(); + return c; + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFEu); os.Put(0xFFu); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put((c >> 8) & 0xFFu); + os.Put(c & 0xFFu); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. +*/ +template +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } +}; + +//! UTF-32 little endian enocoding. +template +struct UTF32LE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take(); + c |= (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take() << 16; + c |= (unsigned char)is.Take() << 24; + return c; + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(c & 0xFFu); + os.Put((c >> 8) & 0xFFu); + os.Put((c >> 16) & 0xFFu); + os.Put((c >> 24) & 0xFFu); + } +}; + +//! UTF-32 big endian encoding. +template +struct UTF32BE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take() << 24; + c |= (unsigned char)is.Take() << 16; + c |= (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take(); + return c; + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put((c >> 24) & 0xFFu); + os.Put((c >> 16) & 0xFFu); + os.Put((c >> 8) & 0xFFu); + os.Put(c & 0xFFu); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast(codepoint & 0xFF)); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + unsigned char c = static_cast(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + unsigned char c = is.Take(); + os.Put(c); + return c <= 0x7F; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + Ch c = Take(is); + return c; + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return is.Take(); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// AutoUTF + +//! Runtime-specified UTF encoding type of a stream. +enum UTFType { + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. +}; + +//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. +/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). +*/ +template +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + + template + RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; + (*f[os.GetType()])(os, codepoint); + } + + template + RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { + typedef bool (*DecodeFunc)(InputStream&, unsigned*); + static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; + return (*f[is.GetType()])(is, codepoint); + } + + template + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + typedef bool (*ValidateFunc)(InputStream&, OutputStream&); + static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; + return (*f[is.GetType()])(is, os); + } + +#undef RAPIDJSON_ENCODINGS_FUNC +}; + +/////////////////////////////////////////////////////////////////////////////// +// Transcoder + +//! Encoding conversion. +template +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +//! Specialization of Transcoder with same source and target encoding. +template +struct Transcoder { + template + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Encoding::Validate(is, os); // source/target encoding are the same + } +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || defined(_MSV_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/contrib/rapidjson/include/rapidjson/error/en.h b/contrib/rapidjson/include/rapidjson/error/en.h new file mode 100644 index 000000000..d5f9caab8 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/error/en.h @@ -0,0 +1,65 @@ +// 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 +// 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_ERROR_EN_H__ +#define RAPIDJSON_ERROR_EN_H__ + +#include "error.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Maps error code of parsing into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param parseErrorCode Error code obtained in parsing. + \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* GetParseError_En(ParseErrorCode parseErrorCode) { + switch (parseErrorCode) { + case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow 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."); + case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); + case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); + case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); + case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); + + case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); + case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); + case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); + + case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); + case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + + default: + return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ERROR_EN_H__ diff --git a/contrib/rapidjson/include/rapidjson/error/error.h b/contrib/rapidjson/include/rapidjson/error/error.h new file mode 100644 index 000000000..f9094fb95 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/error/error.h @@ -0,0 +1,146 @@ +// 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 +// 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_ERROR_ERROR_H__ +#define RAPIDJSON_ERROR_ERROR_H__ + +#include "../rapidjson.h" + +/*! \file error.h */ + +/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_CHARTYPE + +//! Character type of error messages. +/*! \ingroup RAPIDJSON_ERRORS + The default character type is \c char. + On Windows, user can define this macro as \c TCHAR for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_CHARTYPE +#define RAPIDJSON_ERROR_CHARTYPE char +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_STRING + +//! Macro for converting string literial 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 + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_STRING +#define RAPIDJSON_ERROR_STRING(x) x +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseErrorCode + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericReader::Parse, GenericReader::GetParseErrorCode +*/ +enum ParseErrorCode { + kParseErrorNone = 0, //!< No error. + + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + + kParseErrorValueInvalid, //!< Invalid value. + + kParseErrorObjectMissName, //!< Missing a name for object member. + kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. + kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. + + kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. + + kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. + kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. + kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. + kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. + kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. + + kParseErrorNumberTooBig, //!< Number too big to be stored in double. + kParseErrorNumberMissFraction, //!< Miss fraction part in number. + kParseErrorNumberMissExponent, //!< Miss exponent in number. + + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. +}; + +//! Result of parsing (wraps ParseErrorCode) +/*! + \ingroup RAPIDJSON_ERRORS + \code + Document doc; + ParseResult ok = doc.Parse("[42]"); + if (!ok) { + fprintf(stderr, "JSON parse error: %s (%u)", + GetParseError_En(ok.Code()), ok.Offset()); + exit(EXIT_FAILURE); + } + \endcode + \see GenericReader::Parse, GenericDocument::Parse +*/ +struct ParseResult { + + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} + //! Constructor to set an error. + ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} + + //! Get the error code. + ParseErrorCode Code() const { return code_; } + //! Get the error offset, if \ref IsError(), 0 otherwise. + size_t Offset() const { return offset_; } + + //! Conversion to \c bool, returns \c true, iff !\ref IsError(). + operator bool() const { return !IsError(); } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + + bool operator==(const ParseResult& that) const { return code_ == that.code_; } + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. + void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + +private: + ParseErrorCode code_; + size_t offset_; +}; + +//! Function pointer type of GetParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetParseErrorFunc GetParseError = GetParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ERROR_ERROR_H__ diff --git a/contrib/rapidjson/include/rapidjson/filereadstream.h b/contrib/rapidjson/include/rapidjson/filereadstream.h new file mode 100644 index 000000000..3913eb74b --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/filereadstream.h @@ -0,0 +1,88 @@ +// 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 +// 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_FILEREADSTREAM_H_ +#define RAPIDJSON_FILEREADSTREAM_H_ + +#include "rapidjson.h" +#include + +RAPIDJSON_NAMESPACE_BEGIN + +//! File byte stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileReadStream { +public: + typedef char Ch; //!< Character type (byte). + + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 <= bufferLast_) ? current_ : 0; + } + +private: + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } + + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/contrib/rapidjson/include/rapidjson/filewritestream.h b/contrib/rapidjson/include/rapidjson/filewritestream.h new file mode 100644 index 000000000..afd7e19b8 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/filewritestream.h @@ -0,0 +1,95 @@ +// 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 +// 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_FILEWRITESTREAM_H_ +#define RAPIDJSON_FILEWRITESTREAM_H_ + +#include "rapidjson.h" +#include + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of C file stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileWriteStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if (result < static_cast(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; +}; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(FileWriteStream& stream, char c, size_t n) { + stream.PutN(c, n); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/biginteger.h b/contrib/rapidjson/include/rapidjson/internal/biginteger.h new file mode 100644 index 000000000..4477cf5d1 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/biginteger.h @@ -0,0 +1,290 @@ +// 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 +// 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_BIGINTEGER_H_ +#define RAPIDJSON_BIGINTEGER_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include // for _umul128 +#pragma intrinsic(_umul128) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class BigInteger { +public: + typedef uint64_t Type; + + BigInteger(const BigInteger& rhs) : count_(rhs.count_) { + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + + explicit BigInteger(uint64_t u) : count_(1) { + digits_[0] = u; + } + + BigInteger(const char* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; + const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 + while (length >= kMaxDigitPerIteration) { + AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); + length -= kMaxDigitPerIteration; + i += kMaxDigitPerIteration; + } + + if (length > 0) + AppendDecimal64(decimals + i, decimals + i + length); + } + + BigInteger& operator=(const BigInteger &rhs) + { + if (this != &rhs) { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + return *this; + } + + BigInteger& operator=(uint64_t u) { + digits_[0] = u; + count_ = 1; + return *this; + } + + BigInteger& operator+=(uint64_t u) { + Type backup = digits_[0]; + digits_[0] += u; + for (size_t i = 0; i < count_ - 1; i++) { + if (digits_[i] >= backup) + return *this; // no carry + backup = digits_[i + 1]; + digits_[i + 1] += 1; + } + + // Last carry + if (digits_[count_ - 1] < backup) + PushBack(1); + + return *this; + } + + BigInteger& operator*=(uint64_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator*=(uint32_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + const uint64_t c = digits_[i] >> 32; + const uint64_t d = digits_[i] & 0xFFFFFFFF; + const uint64_t uc = u * c; + const uint64_t ud = u * d; + const uint64_t p0 = ud + k; + const uint64_t p1 = uc + (p0 >> 32); + digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); + k = p1 >> 32; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator<<=(size_t shift) { + if (IsZero() || shift == 0) return *this; + + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { + std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type)); + count_ += offset; + } + else { + digits_[count_] = 0; + for (size_t i = count_; i > 0; i--) + digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); + digits_[offset] = digits_[0] << interShift; + count_ += offset; + if (digits_[count_]) + count_++; + } + + std::memset(digits_, 0, offset * sizeof(Type)); + + return *this; + } + + bool operator==(const BigInteger& rhs) const { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } + + bool operator==(const Type rhs) const { + return count_ == 1 && digits_[0] == rhs; + } + + BigInteger& MultiplyPow5(unsigned exp) { + static const uint32_t kPow5[12] = { + 5, + 5 * 5, + 5 * 5 * 5, + 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 + }; + if (exp == 0) return *this; + for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 + for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 + if (exp > 0) *this *= kPow5[exp - 1]; + return *this; + } + + // Compute absolute difference of this and rhs. + // Assume this != rhs + bool Difference(const BigInteger& rhs, BigInteger* out) const { + int cmp = Compare(rhs); + RAPIDJSON_ASSERT(cmp != 0); + const BigInteger *a, *b; // Makes a > b + bool ret; + if (cmp < 0) { a = &rhs; b = this; ret = true; } + else { a = this; b = &rhs; ret = false; } + + Type borrow = 0; + for (size_t i = 0; i < a->count_; i++) { + Type d = a->digits_[i] - borrow; + if (i < b->count_) + d -= b->digits_[i]; + borrow = (d > a->digits_[i]) ? 1 : 0; + out->digits_[i] = d; + if (d != 0) + out->count_ = i + 1; + } + + return ret; + } + + int Compare(const BigInteger& rhs) const { + if (count_ != rhs.count_) + return count_ < rhs.count_ ? -1 : 1; + + for (size_t i = count_; i-- > 0;) + if (digits_[i] != rhs.digits_[i]) + return digits_[i] < rhs.digits_[i] ? -1 : 1; + + return 0; + } + + size_t GetCount() const { return count_; } + Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + +private: + void AppendDecimal64(const char* begin, const char* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + static uint64_t ParseUint64(const char* begin, const char* end) { + uint64_t r = 0; + for (const char* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); + r = r * 10u + (unsigned)(*p - '0'); + } + return r; + } + + // Assume a * b + k < 2^128 + static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t low = _umul128(a, b, outHigh) + k; + if (low < k) + (*outHigh)++; + return low; +#elif (__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; + *outHigh = static_cast(p >> 64); + return static_cast(p); +#else + const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; + uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; + x1 += (x0 >> 32); // can't give carry + x1 += x2; + if (x1 < x2) + x3 += (static_cast(1) << 32); + uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); + uint64_t hi = x3 + (x1 >> 32); + + lo += k; + if (lo < k) + hi++; + *outHigh = hi; + return lo; +#endif + } + + static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 + static const size_t kCapacity = kBitCount / sizeof(Type); + static const size_t kTypeBit = sizeof(Type) * 8; + + Type digits_[kCapacity]; + size_t count_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/diyfp.h b/contrib/rapidjson/include/rapidjson/internal/diyfp.h new file mode 100644 index 000000000..7a55ee31c --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/diyfp.h @@ -0,0 +1,248 @@ +// 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 +// 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. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DIYFP_H_ +#define RAPIDJSON_DIYFP_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include +#pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_umul128) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +struct DiyFp { + DiyFp() {} + + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + + explicit DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + 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__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(f) * static_cast(rhs.f); + uint64_t h = static_cast(p >> 64); + uint64_t l = static_cast(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long index; + _BitScanReverse64(&index, f); + return DiyFp(f << (63 - index), e - (63 - index)); +#elif defined(__GNUC__) && __GNUC__ >= 4 + int s = __builtin_clzll(f); + return DiyFp(f << s, e - s); +#else + DiyFp res = *this; + while (!(res.f & (static_cast(1) << 63))) { + res.f <<= 1; + res.e--; + } + return res; +#endif + } + + DiyFp NormalizeBoundary() const { + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + double ToDouble() const { + union { + double d; + uint64_t u64; + }u; + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMaxExponent = 0x7FF - kDpExponentBias; + static const int kDpMinExponent = -kDpExponentBias; + static const int kDpDenormalExponent = -kDpExponentBias + 1; + static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPowerByIndex(size_t index) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), + RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), + RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), + RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), + RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), + RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), + RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), + RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), + RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), + RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), + RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), + RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), + RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), + RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), + RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), + RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), + RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), + RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), + RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), + RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), + RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), + RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), + RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), + RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), + RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), + RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), + RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), + RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), + RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), + RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), + RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), + RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), + RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), + RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), + RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), + RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), + RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), + RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), + RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), + RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), + RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), + RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast(dk); + if (dk - k > 0.0) + k++; + + unsigned index = static_cast((k >> 3) + 1); + *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table + + return GetCachedPowerByIndex(index); +} + +inline DiyFp GetCachedPower10(int exp, int *outExp) { + unsigned index = (static_cast(exp) + 348u) / 8u; + *outExp = -348 + static_cast(index) * 8; + return GetCachedPowerByIndex(index); + } + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DIYFP_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/dtoa.h b/contrib/rapidjson/include/rapidjson/internal/dtoa.h new file mode 100644 index 000000000..d04ae21cc --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/dtoa.h @@ -0,0 +1,217 @@ +// 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 +// 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. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DTOA_ +#define RAPIDJSON_DTOA_ + +#include "itoa.h" // GetDigitsLut() +#include "diyfp.h" +#include "ieee754.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline unsigned CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + // Will not reach 10 digits in DigitGen() + //if (n < 1000000000) return 9; + //return 10; + return 9; +} + +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 }; + 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); + uint64_t p2 = Mp.f & (one.f - 1); + unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + *len = 0; + + while (kappa > 0) { + uint32_t d = 0; + switch (kappa) { + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default:; + } + if (d || *len) + buffer[(*len)++] = static_cast('0' + static_cast(d)); + kappa--; + 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); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast('0' + d); + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast(kappa)]); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline char* WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = static_cast('0' + static_cast(K / 100)); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = static_cast('0' + static_cast(K)); + + return buffer; +} + +inline char* Prettify(char* buffer, int length, int k) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (length <= kk && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + return &buffer[kk + 2]; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); + buffer[kk] = '.'; + return &buffer[length + 1]; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + std::memmove(&buffer[offset], &buffer[0], static_cast(length)); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + return &buffer[length + offset]; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + return WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + return WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa(double value, char* buffer) { + Double d(value); + if (d.IsZero()) { + if (d.Sign()) + *buffer++ = '-'; // -0.0, Issue #289 + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + return Prettify(buffer, length, K); + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DTOA_ diff --git a/contrib/rapidjson/include/rapidjson/internal/ieee754.h b/contrib/rapidjson/include/rapidjson/internal/ieee754.h new file mode 100644 index 000000000..2fdaf54b3 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/ieee754.h @@ -0,0 +1,77 @@ +// 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 +// 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_IEEE754_ +#define RAPIDJSON_IEEE754_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class Double { +public: + Double() {} + Double(double d) : d_(d) {} + Double(uint64_t u) : u_(u) {} + + double Value() const { return d_; } + uint64_t Uint64Value() const { return u_; } + + double NextPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + return Double(u_ + 1).Value(); + } + + bool Sign() const { return (u_ & kSignMask) != 0; } + uint64_t Significand() const { return u_ & kSignificandMask; } + int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } + + bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } + bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } + + uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } + + static unsigned EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else + return (unsigned)order + 1074; + } + +private: + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const int kDenormalExponent = 1 - kExponentBias; + static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + union { + double d_; + uint64_t u_; + }; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_IEEE754_ diff --git a/contrib/rapidjson/include/rapidjson/internal/itoa.h b/contrib/rapidjson/include/rapidjson/internal/itoa.h new file mode 100644 index 000000000..01a4e7e72 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/itoa.h @@ -0,0 +1,304 @@ +// 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 +// 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_ITOA_ +#define RAPIDJSON_ITOA_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', + '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', + '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', + '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', + '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', + '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', + '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', + '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', + '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', + '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' + }; + return cDigitsLut; +} + +inline char* u32toa(uint32_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + + if (value < 10000) { + const uint32_t d1 = (value / 100) << 1; + const uint32_t d2 = (value % 100) << 1; + + if (value >= 1000) + *buffer++ = cDigitsLut[d1]; + if (value >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else if (value < 100000000) { + // value = bbbbcccc + const uint32_t b = value / 10000; + const uint32_t c = value % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + else { + // value = aabbbbcccc in decimal + + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; + + if (a >= 10) { + const unsigned i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else + *buffer++ = static_cast('0' + static_cast(a)); + + const uint32_t b = value / 10000; // 0 to 9999 + const uint32_t c = value % 10000; // 0 to 9999 + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + return buffer; +} + +inline char* i32toa(int32_t value, char* buffer) { + uint32_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u32toa(u, buffer); +} + +inline char* u64toa(uint64_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; + const uint64_t kTen10 = kTen8 * 100; + const uint64_t kTen11 = kTen8 * 1000; + const uint64_t kTen12 = kTen8 * 10000; + const uint64_t kTen13 = kTen8 * 100000; + const uint64_t kTen14 = kTen8 * 1000000; + const uint64_t kTen15 = kTen8 * 10000000; + const uint64_t kTen16 = kTen8 * kTen8; + + if (value < kTen8) { + uint32_t v = static_cast(value); + if (v < 10000) { + const uint32_t d1 = (v / 100) << 1; + const uint32_t d2 = (v % 100) << 1; + + if (v >= 1000) + *buffer++ = cDigitsLut[d1]; + if (v >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (v >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else { + // value = bbbbcccc + const uint32_t b = v / 10000; + const uint32_t c = v % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + } + else if (value < kTen16) { + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + if (value >= kTen15) + *buffer++ = cDigitsLut[d1]; + if (value >= kTen14) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= kTen13) + *buffer++ = cDigitsLut[d2]; + if (value >= kTen12) + *buffer++ = cDigitsLut[d2 + 1]; + if (value >= kTen11) + *buffer++ = cDigitsLut[d3]; + if (value >= kTen10) + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; + if (value >= kTen8) + *buffer++ = cDigitsLut[d4 + 1]; + + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + else { + const uint32_t a = static_cast(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast('0' + static_cast(a)); + else if (a < 100) { + const uint32_t i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else if (a < 1000) { + *buffer++ = static_cast('0' + static_cast(a / 100)); + + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else { + const uint32_t i = (a / 100) << 1; + const uint32_t j = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } + + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + + return buffer; +} + +inline char* i64toa(int64_t value, char* buffer) { + uint64_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u64toa(u, buffer); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ITOA_ diff --git a/contrib/rapidjson/include/rapidjson/internal/meta.h b/contrib/rapidjson/include/rapidjson/internal/meta.h new file mode 100644 index 000000000..5a9aaa428 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/meta.h @@ -0,0 +1,181 @@ +// 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 +// 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_INTERNAL_META_H_ +#define RAPIDJSON_INTERNAL_META_H_ + +#include "../rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif +#if defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(6334) +#endif + +#if RAPIDJSON_HAS_CXX11_TYPETRAITS +#include +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType TrueType; +typedef BoolType FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; +template struct SelectIfCond : SelectIfImpl::template Apply {}; +template struct SelectIf : SelectIfCond {}; + +template struct AndExprCond : FalseType {}; +template <> struct AndExprCond : TrueType {}; +template struct OrExprCond : TrueType {}; +template <> struct OrExprCond : FalseType {}; + +template struct BoolExpr : SelectIf::Type {}; +template struct NotExpr : SelectIf::Type {}; +template struct AndExpr : AndExprCond::Type {}; +template struct OrExpr : OrExprCond::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template struct AddConst { typedef const T Type; }; +template struct MaybeAddConst : SelectIfCond {}; +template struct RemoveConst { typedef T Type; }; +template struct RemoveConst { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template struct IsSame : FalseType {}; +template struct IsSame : TrueType {}; + +template struct IsConst : FalseType {}; +template struct IsConst : TrueType {}; + +template +struct IsMoreConst + : AndExpr::Type, typename RemoveConst::Type>, + BoolType::Value >= IsConst::Value> >::Type {}; + +template struct IsPointer : FalseType {}; +template struct IsPointer : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template struct IsBaseOf + : BoolType< ::std::is_base_of::value> {}; + +#else // simplified version adopted from Boost + +template struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template + static Yes Check(const D*, T); + static No Check(const B*, int); + + struct Host { + operator const B*() const; + operator const D*(); + }; + + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; +}; + +template struct IsBaseOf + : OrExpr, BoolExpr > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template struct EnableIfCond { typedef T Type; }; +template struct EnableIfCond { /* empty */ }; + +template struct DisableIfCond { typedef T Type; }; +template struct DisableIfCond { /* empty */ }; + +template +struct EnableIf : EnableIfCond {}; + +template +struct DisableIf : DisableIfCond {}; + +// SFINAE helpers +struct SfinaeTag {}; +template struct RemoveSfinaeTag; +template struct RemoveSfinaeTag { typedef T Type; }; + +#define RAPIDJSON_REMOVEFPTR_(type) \ + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + +#define RAPIDJSON_ENABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type + +} // namespace internal +RAPIDJSON_NAMESPACE_END +//@endcond + +#if defined(__GNUC__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_META_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/pow10.h b/contrib/rapidjson/include/rapidjson/internal/pow10.h new file mode 100644 index 000000000..02f475d70 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/pow10.h @@ -0,0 +1,55 @@ +// 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 +// 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_POW10_ +#define RAPIDJSON_POW10_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n non-negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POW10_ diff --git a/contrib/rapidjson/include/rapidjson/internal/stack.h b/contrib/rapidjson/include/rapidjson/internal/stack.h new file mode 100644 index 000000000..344785dcd --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/stack.h @@ -0,0 +1,196 @@ +// 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 +// 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_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +#include "../rapidjson.h" +#include "swap.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template +class Stack { +public: + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + RAPIDJSON_ASSERT(stackCapacity > 0); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); + } + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + // Expand the stack if needed + if (stackTop_ + sizeof(T) * count >= stackEnd_) + Expand(count); + + T* ret = reinterpret_cast(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast(stackTop_); + } + + template + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + T* Bottom() { return (T*)stack_; } + + bool HasAllocator() const { + return allocator_ != 0; + } + + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } + +private: + template + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STACK_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/strfunc.h b/contrib/rapidjson/include/rapidjson/internal/strfunc.h new file mode 100644 index 000000000..84405065a --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/strfunc.h @@ -0,0 +1,39 @@ +// 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 +// 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_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template +inline SizeType StrLen(const Ch* s) { + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/strtod.h b/contrib/rapidjson/include/rapidjson/internal/strtod.h new file mode 100644 index 000000000..a1b821197 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/strtod.h @@ -0,0 +1,270 @@ +// 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 +// 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_STRTOD_ +#define RAPIDJSON_STRTOD_ + +#include "../rapidjson.h" +#include "ieee754.h" +#include "biginteger.h" +#include "diyfp.h" +#include "pow10.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline double FastPath(double significand, int exp) { + if (exp < -308) + return 0.0; + else if (exp >= 0) + return significand * internal::Pow10(exp); + else + return significand / internal::Pow10(-exp); +} + +inline double StrtodNormalPrecision(double d, int p) { + if (p < -308) { + // Prevent expSum < -308, making Pow10(p) = 0 + d = FastPath(d, -308); + d = FastPath(d, p + 308); + } + else + d = FastPath(d, p); + return d; +} + +template +inline T Min3(T a, T b, T c) { + T m = a; + if (m > b) m = b; + if (m > c) m = c; + return m; +} + +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { + const Double db(b); + const uint64_t bInt = db.IntegerSignificand(); + const int bExp = db.IntegerExponent(); + const int hExp = bExp - 1; + + int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + BigInteger dS = d; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); + + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); + + BigInteger hS(1); + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); + + BigInteger delta(0); + dS.Difference(bS, &delta); + + return delta.Compare(hS); +} + +inline bool StrtodFast(double d, int p, double* result) { + // Use fast path for string-to-double conversion if possible + // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ + if (p > 22 && p < 22 + 16) { + // Fast Path Cases In Disguise + d *= internal::Pow10(p - 22); + p = 22; + } + + if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 + *result = FastPath(d, p); + return true; + } + else + return false; +} + +// Compute an approximation and see if it is within 1/2 ULP +inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) { + uint64_t significand = 0; + size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 + for (; i < length; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) + break; + significand = significand * 10u + static_cast(decimals[i] - '0'); + } + + if (i < length && decimals[i] >= '5') // Rounding + significand++; + + size_t remaining = length - i; + const unsigned kUlpShift = 3; + const unsigned kUlp = 1 << kUlpShift; + int error = (remaining == 0) ? 0 : kUlp / 2; + + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; + + const int dExp = (int)decimalPosition - (int)i + exp; + + int actualExp; + DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); + if (actualExp != dExp) { + static const DiyFp kPow10[] = { + DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1 + DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2 + DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3 + DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4 + DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5 + DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 + DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 + }; + int adjustment = dExp - actualExp - 1; + RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); + v = v * kPow10[adjustment]; + if (length + static_cast(adjustment)> 19u) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + + v = v * cachedPower; + + error += kUlp + (error == 0 ? 0 : 1); + + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; + + const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + unsigned precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { + unsigned scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; + error = (error >> scaleExp) + 1 + static_cast(kUlp); + precisionSize -= scaleExp; + } + + DiyFp rounded(v.f >> precisionSize, v.e + static_cast(precisionSize)); + const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; + const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; + if (precisionBits >= halfWay + static_cast(error)) { + rounded.f++; + if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) + rounded.f >>= 1; + rounded.e++; + } + } + + *result = rounded.ToDouble(); + + return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); +} + +inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { + const BigInteger dInt(decimals, length); + const int dExp = (int)decimalPosition - (int)length + exp; + Double a(approx); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return a.NextPositiveDouble(); + else + return a.Value(); + } + else // adjustment + return a.NextPositiveDouble(); +} + +inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + + double result; + if (StrtodFast(d, p, &result)) + return result; + + // Trim leading zeros + while (*decimals == '0' && length > 1) { + length--; + decimals++; + decimalPosition--; + } + + // Trim trailing zeros + while (decimals[length - 1] == '0' && length > 1) { + length--; + decimalPosition--; + exp++; + } + + // Trim right-most digits + const int kMaxDecimalDigit = 780; + if ((int)length > kMaxDecimalDigit) { + int delta = (int(length) - kMaxDecimalDigit); + exp += delta; + decimalPosition -= static_cast(delta); + length = kMaxDecimalDigit; + } + + // If too small, underflow to zero + if (int(length) + exp < -324) + return 0.0; + + if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison + return StrtodBigInteger(result, decimals, length, decimalPosition, exp); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRTOD_ diff --git a/contrib/rapidjson/include/rapidjson/internal/swap.h b/contrib/rapidjson/include/rapidjson/internal/swap.h new file mode 100644 index 000000000..0590921f1 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/swap.h @@ -0,0 +1,37 @@ +// 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 +// 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_INTERNAL_SWAP_H_ +#define RAPIDJSON_INTERNAL_SWAP_H_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom swap() to avoid dependency on C++ header +/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. + \note This has the same semantics as std::swap(). +*/ +template +inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { + T tmp = a; + a = b; + b = tmp; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/contrib/rapidjson/include/rapidjson/memorybuffer.h b/contrib/rapidjson/include/rapidjson/memorybuffer.h new file mode 100644 index 000000000..2484b2185 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/memorybuffer.h @@ -0,0 +1,70 @@ +// 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 +// 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_MEMORYBUFFER_H_ +#define RAPIDJSON_MEMORYBUFFER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output byte stream. +/*! + This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. + + It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. + + Differences between MemoryBuffer and StringBuffer: + 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. + 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. + + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; +}; + +typedef GenericMemoryBuffer<> MemoryBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { + std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/contrib/rapidjson/include/rapidjson/memorystream.h b/contrib/rapidjson/include/rapidjson/memorystream.h new file mode 100644 index 000000000..99feae5d7 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/memorystream.h @@ -0,0 +1,61 @@ +// 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 +// 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_MEMORYSTREAM_H_ +#define RAPIDJSON_MEMORYSTREAM_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory input byte stream. +/*! + This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. + + It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. + + Differences between MemoryStream and StringStream: + 1. StringStream has encoding but MemoryStream is a byte stream. + 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. + 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). + \note implements Stream concept +*/ +struct MemoryStream { + typedef char Ch; // byte + + MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + + Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } + Ch Take() { return (src_ == end_) ? '\0' : *src_++; } + size_t Tell() const { return static_cast(src_ - begin_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return Tell() + 4 <= size_ ? src_ : 0; + } + + const Ch* src_; //!< Current read position. + const Ch* begin_; //!< Original head of the string. + const Ch* end_; //!< End of stream. + size_t size_; //!< Size of the stream. +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h b/contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h new file mode 100644 index 000000000..18111286b --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h @@ -0,0 +1,316 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// miloyip: VC supports inttypes.h since VC2013 +#if _MSC_VER >= 1800 +#include +#else + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + +#endif // _MSC_VER >= 1800 + +#endif // _MSC_INTTYPES_H_ ] diff --git a/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h b/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h new file mode 100644 index 000000000..a26fff4bf --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h @@ -0,0 +1,300 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. +#if _MSC_VER >= 1600 // [ +#include + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +#undef INT8_C +#undef INT16_C +#undef INT32_C +#undef INT64_C +#undef UINT8_C +#undef UINT16_C +#undef UINT32_C +#undef UINT64_C + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#else // ] _MSC_VER >= 1700 [ + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] diff --git a/contrib/rapidjson/include/rapidjson/pointer.h b/contrib/rapidjson/include/rapidjson/pointer.h new file mode 100644 index 000000000..5d2aa8d63 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/pointer.h @@ -0,0 +1,1313 @@ +// 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 +// 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_POINTER_H_ +#define RAPIDJSON_POINTER_H_ + +#include "document.h" +#include "internal/itoa.h" + +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 + +//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. +/*! + This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" + (https://tools.ietf.org/html/rfc6901). + + A JSON pointer is for identifying a specific value in a JSON document + (GenericDocument). It can simplify coding of DOM tree manipulation, because it + can access multiple-level depth of DOM tree with single API call. + + After it parses a string representation (e.g. "/foo/0" or URI fragment + representation (e.g. "#/foo/0") into its internal representation (tokens), + it can be used to resolve a specific value in multiple documents, or sub-tree + of documents. + + Contrary to GenericValue, Pointer can be copy constructed and copy assigned. + Apart from assignment, a Pointer cannot be modified after construction. + + Although Pointer is very convenient, please aware that constructing Pointer + involves parsing and dynamic memory allocation. A special constructor with user- + 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. +*/ +template +class GenericPointer { +public: + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename EncodingType::Ch Ch; //!< Character type from Value + + //! 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. + They are resolved according to the actual value type (object or array). + + For token that are not numbers, or the numeric value is out of bound + (greater than limits of SizeType), they are only treated as string form + (i.e. the token's index will be equal to kPointerInvalidIndex). + + This struct is public so that user can create a Pointer without parsing and + allocation, using a special constructor. + */ + struct Token { + const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. + SizeType length; //!< Length of the name. + SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. + }; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor. + GenericPointer() : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A null-terminated, string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + */ + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, internal::StrLen(source)); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source.c_str(), source.size()); + } +#endif + + //! Constructor that parses a string or URI fragment representation, with length of the source string. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param length Length of source. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Slightly faster than the overload without length. + */ + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, length); + } + + //! Constructor with user-supplied tokens. + /*! + This constructor let user supplies const array of tokens. + This prevents the parsing process and eliminates allocation. + This is preferred for memory constrained environments. + + \param tokens An constant array of tokens representing the JSON pointer. + \param tokenCount Number of tokens. + + \b Example + \code + #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } + #define INDEX(i) { #i, sizeof(#i) - 1, i } + + static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; + static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + // Equivalent to static const Pointer p("/foo/123"); + + #undef NAME + #undef INDEX + \endcode + */ + 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_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Destructor. + ~GenericPointer() { + if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. + Allocator::Free(tokens_); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator. + GenericPointer& operator=(const GenericPointer& rhs) { + if (this != &rhs) { + // Do not delete ownAllcator + if (nameBuffer_) + Allocator::Free(tokens_); + + tokenCount_ = rhs.tokenCount_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; + + if (rhs.nameBuffer_) + CopyFromRaw(rhs); // Normally parsed tokens. + else { + tokens_ = rhs.tokens_; // User supplied const tokens. + nameBuffer_ = 0; + } + } + return *this; + } + + //@} + + //!@name Append token + //@{ + + //! Append a token and return a new Pointer + /*! + \param token Token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Token& token, Allocator* allocator = 0) const { + GenericPointer r; + r.allocator_ = allocator; + Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); + std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); + r.tokens_[tokenCount_].name = p; + r.tokens_[tokenCount_].length = token.length; + r.tokens_[tokenCount_].index = token.index; + return r; + } + + //! Append a name token with length, and return a new Pointer + /*! + \param name Name to be appended. + \param length Length of name. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { + Token token = { name, length, kPointerInvalidIndex }; + return Append(token, allocator); + } + + //! Append a name token without length, and return a new Pointer + /*! + \param name Name (const Ch*) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const { + return Append(name, StrLen(name), allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Append a name token, and return a new Pointer + /*! + \param name Name to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const std::basic_string& name, Allocator* allocator = 0) const { + return Append(name.c_str(), static_cast(name.size()), allocator); + } +#endif + + //! Append a index token, and return a new Pointer + /*! + \param index Index to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(SizeType index, Allocator* allocator = 0) const { + char buffer[21]; + SizeType length = (sizeof(SizeType) == 4 ? internal::u32toa(index, buffer): internal::u64toa(index, buffer)) - buffer; + buffer[length] = '\0'; + + if (sizeof(Ch) == 1) { + Token token = { (Ch*)buffer, length, index }; + return Append(token, allocator); + } + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) + name[i] = buffer[i]; + Token token = { name, length, index }; + return Append(token, allocator); + } + } + + //! Append a token by value, and return a new Pointer + /*! + \param value Value (either Uint or String) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { + if (token.IsString()) + return Append(token.GetString(), token.GetStringLength(), allocator); + else { + RAPIDJSON_ASSERT(token.IsUint64()); + RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); + return Append(static_cast(token.GetUint64()), allocator); + } + } + + //!@name Handling Parse Error + //@{ + + //! Check whether this is a valid pointer. + bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + + //! Get the parsing error offset in code unit. + size_t GetParseErrorOffset() const { return parseErrorOffset_; } + + //! Get the parsing error code. + PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } + + //@} + + //!@name Tokens + //@{ + + //! Get the token array (const version only). + const Token* GetTokens() const { return tokens_; } + + //! Get the number of tokens. + size_t GetTokenCount() const { return tokenCount_; } + + //@} + + //!@name Equality/inequality operators + //@{ + + //! Equality operator. + /*! + \note When any pointers are invalid, always returns false. + */ + bool operator==(const GenericPointer& rhs) const { + if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) + return false; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index || + tokens_[i].length != rhs.tokens_[i].length || + (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) + { + return false; + } + } + + return true; + } + + //! Inequality operator. + /*! + \note When any pointers are invalid, always returns true. + */ + bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + + //@} + + //!@name Stringify + //@{ + + //! Stringify the pointer into string representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + return Stringify(os); + } + + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool StringifyUriFragment(OutputStream& os) const { + return Stringify(os); + } + + //@} + + //!@name Create value + //@{ + + //! Create a value in a subtree. + /*! + If the value is not exist, it creates all parent values and a JSON Null value. + So it always succeed and return the newly created or existing value. + + Remind that it may change types of parents according to tokens, so it + potentially removes previously stored values. For example, if a document + was an array, and "/foo" is used to create a value, then the document + will be changed to an object, and all existing array elements are lost. + + \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created (a JSON Null value), or already exists value. + */ + ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + bool exist = true; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + if (v->IsArray() && t->name[0] == '-' && t->length == 1) { + v->PushBack(Value().Move(), allocator); + v = &((*v)[v->Size() - 1]); + exist = false; + } + else { + if (t->index == kPointerInvalidIndex) { // must be object name + if (!v->IsObject()) + v->SetObject(); // Change to Object + } + else { // object name or array index + if (!v->IsArray() && !v->IsObject()) + v->SetArray(); // Change to Array + } + + if (v->IsArray()) { + if (t->index >= v->Size()) { + v->Reserve(t->index + 1, allocator); + while (t->index >= v->Size()) + v->PushBack(Value().Move(), allocator); + exist = false; + } + v = &((*v)[t->index]); + } + else { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) { + v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); + v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end + exist = false; + } + else + v = &m->value; + } + } + } + + if (alreadyExist) + *alreadyExist = exist; + + return *v; + } + + //! Creates a value in a document. + /*! + \param document A document to be resolved. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created, or already exists value. + */ + template + ValueType& Create(GenericDocument& document, bool* alreadyExist = 0) const { + return Create(document, document.GetAllocator(), alreadyExist); + } + + //@} + + //!@name Query value + //@{ + + //! Query a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ + ValueType* Get(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) + return 0; + v = &m->value; + } + break; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + return 0; + v = &((*v)[t->index]); + break; + default: + return 0; + } + } + return v; + } + + //! Query a const value in a const subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ + const ValueType* Get(const ValueType& root) const { return Get(const_cast(root)); } + + //@} + + //!@name Query a value with default + //@{ + + //! Query a value in a subtree with default value. + /*! + Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. + So that this function always succeed. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param defaultValue Default value to be cloned if the value was not exists. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); + } + + //! Query a value in a subtree with default null-terminated string. + ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a subtree with default std::basic_string. + ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } +#endif + + //! Query a value in a subtree with default primitive value. + /*! + \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { + return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); + } + + //! Query a value in a document with default value. + template + ValueType& GetWithDefault(GenericDocument& document, const ValueType& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //! Query a value in a document with default null-terminated string. + template + 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 + ValueType& GetWithDefault(GenericDocument& document, const std::basic_string& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } +#endif + + //! Query a value in a document with default primitive value. + /*! + \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(GenericDocument& document, T defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //@} + + //!@name Set a value + //@{ + + //! Set a value in a subtree, with move semantics. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be set. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = value; + } + + //! Set a value in a subtree, with copy semantics. + ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).CopyFrom(value, allocator); + } + + //! Set a null-terminated string in a subtree. + ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Set a std::basic_string in a subtree. + ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } +#endif + + //! Set a primitive value in a subtree. + /*! + \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value).Move(); + } + + //! Set a value in a document, with move semantics. + template + ValueType& Set(GenericDocument& document, ValueType& value) const { + return Create(document) = value; + } + + //! Set a value in a document, with copy semantics. + template + ValueType& Set(GenericDocument& document, const ValueType& value) const { + return Create(document).CopyFrom(value, document.GetAllocator()); + } + + //! Set a null-terminated string in a document. + template + ValueType& Set(GenericDocument& document, const Ch* value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Sets a std::basic_string in a document. + template + ValueType& Set(GenericDocument& document, const std::basic_string& value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } +#endif + + //! Set a primitive value in a document. + /*! + \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(GenericDocument& document, T value) const { + return Create(document) = value; + } + + //@} + + //!@name Swap a value + //@{ + + //! Swap a value with a value in a subtree. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be swapped. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).Swap(value); + } + + //! Swap a value with a value in a document. + template + ValueType& Swap(GenericDocument& document, ValueType& value) const { + return Create(document).Swap(value); + } + + //@} + + //! Erase a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Whether the resolved value is found and erased. + + \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. + */ + bool Erase(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + if (tokenCount_ == 0) // Cannot erase the root + return false; + + ValueType* v = &root; + const Token* last = tokens_ + (tokenCount_ - 1); + for (const Token *t = tokens_; t != last; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) + return false; + v = &m->value; + } + break; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + return false; + v = &((*v)[t->index]); + break; + default: + return false; + } + } + + switch (v->GetType()) { + case kObjectType: + return v->EraseMember(GenericStringRef(last->name, last->length)); + case kArrayType: + if (last->index == kPointerInvalidIndex || last->index >= v->Size()) + return false; + v->Erase(v->Begin() + last->index); + return true; + default: + return false; + } + } + +private: + //! Clone the content from rhs to this. + /*! + \param rhs Source pointer. + \param extraToken Extra tokens to be allocated. + \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. + \return Start of non-occupied name buffer, for storing extra names. + */ + Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { + if (!allocator_) // allocator is independently owned. + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens + for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) + nameBufferSize += t->length; + + tokenCount_ = rhs.tokenCount_ + extraToken; + tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + 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; + + return nameBuffer_ + nameBufferSize; + } + + //! Check whether a character should be percent-encoded. + /*! + According to RFC 3986 2.3 Unreserved Characters. + \param c The character (code unit) to be tested. + */ + bool NeedPercentEncode(Ch c) const { + return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); + } + + //! Parse a JSON String or its URI fragment representation into tokens. + /*! + \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. + \param length Length of the source string. + \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. + */ + void Parse(const Ch* source, size_t length) { + RAPIDJSON_ASSERT(source != NULL); + RAPIDJSON_ASSERT(nameBuffer_ == 0); + RAPIDJSON_ASSERT(tokens_ == 0); + + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + // Count number of '/' as tokenCount + tokenCount_ = 0; + for (const Ch* s = source; s != source + length; s++) + if (*s == '/') + tokenCount_++; + + Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); + Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + size_t i = 0; + + // Detect if it is a URI fragment + bool uriFragment = false; + if (source[i] == '#') { + uriFragment = true; + i++; + } + + if (i != length && source[i] != '/') { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } + + while (i < length) { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' + + token->name = name; + bool isNumber = true; + + while (i < length && source[i] != '/') { + Ch c = source[i]; + if (uriFragment) { + // Decoding percent-encoding for URI fragment + if (c == '%') { + PercentDecodeStream is(&source[i], source + length); + GenericInsituStringStream os(name); + Ch* begin = os.PutBegin(); + if (!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + size_t len = os.PutEnd(begin); + i += is.Tell() - 1; + if (len == 1) + c = *name; + else { + name += len; + isNumber = false; + i++; + continue; + } + } + else if (NeedPercentEncode(c)) { + parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; + goto error; + } + } + + i++; + + // Escaping "~0" -> '~', "~1" -> '/' + if (c == '~') { + if (i < length) { + c = source[i]; + if (c == '0') c = '~'; + else if (c == '1') c = '/'; + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; + } + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + } + + // First check for index: all of characters are digit + if (c < '0' || c > '9') + isNumber = false; + + *name++ = c; + } + token->length = name - token->name; + if (token->length == 0) + isNumber = false; + *name++ = '\0'; // Null terminator + + // Second check for index: more than one digit cannot have leading zero + if (isNumber && token->length > 1 && token->name[0] == '0') + isNumber = false; + + // String to SizeType conversion + SizeType n = 0; + if (isNumber) { + for (size_t j = 0; j < token->length; j++) { + SizeType m = n * 10 + static_cast(token->name[j] - '0'); + if (m < n) { // overflow detection + isNumber = false; + break; + } + n = m; + } + } + + token->index = isNumber ? n : kPointerInvalidIndex; + token++; + } + + RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer + parseErrorCode_ = kPointerParseErrorNone; + return; + + error: + Allocator::Free(tokens_); + nameBuffer_ = 0; + tokens_ = 0; + tokenCount_ = 0; + parseErrorOffset_ = i; + return; + } + + //! Stringify to string or URI fragment representation. + /*! + \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. + \tparam OutputStream type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + RAPIDJSON_ASSERT(IsValid()); + + if (uriFragment) + os.Put('#'); + + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + os.Put('/'); + for (size_t j = 0; j < t->length; j++) { + Ch c = t->name[j]; + if (c == '~') { + os.Put('~'); + os.Put('0'); + } + else if (c == '/') { + os.Put('~'); + os.Put('1'); + } + else if (uriFragment && NeedPercentEncode(c)) { + // Transcode to UTF8 sequence + GenericStringStream source(&t->name[j]); + PercentEncodeStream target(os); + if (!Transcoder >().Validate(source, target)) + return false; + j += source.Tell() - 1; + } + else + os.Put(c); + } + } + return true; + } + + //! A helper stream for decoding a percent-encoded sequence into code unit. + /*! + This stream decodes %XY triplet into code unit (0-255). + If it encounters invalid characters, it sets output code unit as 0 and + mark invalid, and to be checked by IsValid(). + */ + class PercentDecodeStream { + public: + //! Constructor + /*! + \param source Start of the stream + \param end Past-the-end of the stream. + */ + PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} + + Ch Take() { + if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet + valid_ = false; + return 0; + } + src_++; + Ch c = 0; + for (int j = 0; j < 2; j++) { + c <<= 4; + Ch h = *src_; + if (h >= '0' && h <= '9') c += h - '0'; + else if (h >= 'A' && h <= 'F') c += h - 'A' + 10; + else if (h >= 'a' && h <= 'f') c += h - 'a' + 10; + else { + valid_ = false; + return 0; + } + src_++; + } + return c; + } + + size_t Tell() const { return src_ - head_; } + bool IsValid() const { return valid_; } + + private: + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. + const Ch* end_; //!< Past-the-end position. + bool valid_; //!< Whether the parsing is valid. + }; + + //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. + template + class PercentEncodeStream { + public: + PercentEncodeStream(OutputStream& os) : os_(os) {} + void Put(char c) { // UTF-8 must be byte + unsigned char u = static_cast(c); + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + os_.Put('%'); + os_.Put(hexDigits[u >> 4]); + os_.Put(hexDigits[u & 15]); + } + private: + OutputStream& os_; + }; + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Pointer. + Ch* nameBuffer_; //!< A buffer containing all names in tokens. + Token* tokens_; //!< A list of tokens. + size_t tokenCount_; //!< Number of tokens in tokens_. + size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. + PointerParseErrorCode parseErrorCode_; //!< Parsing error code. +}; + +//! GenericPointer for Value (UTF-8, default allocator). +typedef GenericPointer Pointer; + +//!@name Helper functions for GenericPointer +//@{ + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Create(root, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer& pointer) { + return pointer.Create(document); +} + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Create(document); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Get(root); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer) { + return pointer.Get(root); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { + return GenericPointer(source, N - 1).Get(root); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Get(root); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const std::basic_string& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, T2 defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* value) { + return pointer.Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const std::basic_string& value) { + return pointer.Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const GenericPointer& pointer, T2 value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string& value) { + return GenericPointer(source, N - 1).Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Swap(root, value, a); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Swap(document, value); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Swap(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +bool EraseValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Erase(root); +} + +template +bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Erase(root); +} + +//@} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POINTER_H_ diff --git a/contrib/rapidjson/include/rapidjson/prettywriter.h b/contrib/rapidjson/include/rapidjson/prettywriter.h new file mode 100644 index 000000000..416dd492e --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/prettywriter.h @@ -0,0 +1,207 @@ +// 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 +// 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_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Writer with indentation and spacing. +/*! + \tparam OutputStream Type of ouptut os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> +class PrettyWriter : public Writer { +public: + typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + PrettyPrefix(kStringType); + return Base::WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndObject(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndArray(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} +protected: + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + Base::os_->Put('\n'); + } + else + Base::os_->Put('\n'); + WriteIndent(); + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, indentChar_, count); + } + + Ch indentChar_; + unsigned indentCharCount_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/contrib/rapidjson/include/rapidjson/rapidjson.h b/contrib/rapidjson/include/rapidjson/rapidjson.h new file mode 100644 index 000000000..b83f8e22f --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/rapidjson.h @@ -0,0 +1,654 @@ +// 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 +// 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_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + Some RapidJSON features are configurable to adapt the library to a wide + variety of platforms, environments and usage scenarios. Most of the + features can be configured in terms of overriden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include // malloc(), realloc(), free(), size_t +#include // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in ".." string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 0 +#define RAPIDJSON_PATCH_VERSION 2 +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ +#ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#ifdef _MSC_VER +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" +#else +// Other compilers should have this. +#include +#include +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && !defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp +*/ +#ifndef RAPIDJSON_ENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(RAPIDJSON_DOXYGEN_RUNNING) +# define RAPIDJSON_ENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || defined(_WIN64) || defined(__EMSCRIPTEN__) +#define RAPIDJSON_64BIT 1 +#else +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. Currently the default uses 4 bytes + alignment. User can customize by defining the RAPIDJSON_ALIGN function macro. +*/ +#ifndef RAPIDJSON_ALIGN +#if RAPIDJSON_64BIT == 1 +#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) +#else +#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 + +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast(high32) << 32) | static_cast(low32)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2 optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible + processors. + + To enable these optimizations, two different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 + + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode + + \c RAPIDJSON_SSE42 takes precedence, if both are defined. + + If any of these symbols is defined, RapidJSON defines the macro + \c RAPIDJSON_SIMD to indicate the availability of the optimized code. +*/ +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ + || defined(RAPIDJSON_DOXYGEN_RUNNING) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +RAPIDJSON_NAMESPACE_END +#endif + +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. +*/ +#ifndef RAPIDJSON_ASSERT +#include +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_STATIC_ASSERT + +// Adopt from boost +#ifndef RAPIDJSON_STATIC_ASSERT +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +RAPIDJSON_NAMESPACE_BEGIN +template struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; +template struct StaticAssertTest {}; +RAPIDJSON_NAMESPACE_END + +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y + +#if defined(__GNUC__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +//!@endcond + +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Helpers + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_END \ +} while((void)0, 0) + +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) + +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif + +#elif defined(_MSC_VER) + +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) + +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) + +#else + +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ + +#endif // RAPIDJSON_DIAG_* + +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \ + (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if 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 >= ????) // not yet supported +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT /* noexcept */ +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif + +//!@endcond + +/////////////////////////////////////////////////////////////////////////////// +// new/delete + +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(x) new x +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Allocators and Encodings + +#include "allocators.h" +#include "encodings.h" + +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits. + */ + enum { copyOptimization = 0 }; +}; + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + for (size_t i = 0; i < n; i++) + stream.Put(c); +} + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream > InsituStringStream; + +/////////////////////////////////////////////////////////////////////////////// +// Type + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/contrib/rapidjson/include/rapidjson/reader.h b/contrib/rapidjson/include/rapidjson/reader.h new file mode 100644 index 000000000..6fb29e908 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/reader.h @@ -0,0 +1,1510 @@ +// 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 +// 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_READER_H_ +#define RAPIDJSON_READER_H_ + +/*! \file reader.h */ + +#include "rapidjson.h" +#include "encodings.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strtod.h" + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (HasParseError()) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END +#endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + +//! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ +enum ParseFlag { + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. +\code +concept Handler { + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \note implements Handler concept +*/ +template, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast(*this).Default(); } + bool Bool(bool) { return static_cast(*this).Default(); } + bool Int(int) { return static_cast(*this).Default(); } + bool Uint(unsigned) { return static_cast(*this).Default(); } + bool Int64(int64_t) { return static_cast(*this).Default(); } + bool Uint64(uint64_t) { return static_cast(*this).Default(); } + bool Double(double) { return static_cast(*this).Default(); } + bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } + bool StartObject() { return static_cast(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast(*this).Default(); } + bool StartArray() { return static_cast(*this).Default(); } + bool EndArray(SizeType) { return static_cast(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); + + for (;; p += 16) { + const __m128i s = _mm_load_si128((const __m128i *)p); + const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r != 0) { // some of characters is non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + static const char whitespaces[4][17] = { + " ", + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", + "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; + + const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); + const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); + const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); + const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); + + for (;; p += 16) { + const __m128i s = _mm_load_si128((const __m128i *)p); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = (unsigned short)~_mm_movemask_epi8(x); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#endif // RAPIDJSON_SSE2 + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& is) { + is.src_ = SkipWhitespace_SIMD(is.src_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam SourceEncoding Encoding of the input stream. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. +*/ +template +class GenericReader { +public: + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (is.Peek() == '\0') { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (is.Peek() != '\0') { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse(is, handler); + } + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + +private: + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + template + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (is.Peek() == '/') { + is.Take(); + + if (is.Peek() == '*') { + is.Take(); + while (true) { + if (is.Peek() == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + if (is.Take() == '*') { + if (is.Peek() == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + if (is.Take() == '/') + break; + } + } + } else if (is.Peek() == '/') { + is.Take(); + while (is.Peek() != '\0' && is.Take() != '\n') { } + } else { + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + } + + SkipWhitespace(is); + } + } + } + + // Parse object: { string : value, ... } + template + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (!handler.StartObject()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (is.Peek() == '}') { + is.Take(); + if (!handler.EndObject(0)) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (is.Peek() != '"') + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (is.Take() != ':') + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++memberCount; + + switch (is.Take()) { + case ',': + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + if (!handler.EndObject(memberCount)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + break; + } + } + } + + // Parse array: [ value, ... ] + template + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (!handler.StartArray()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (is.Peek() == ']') { + is.Take(); + if (!handler.EndArray(0)) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + switch (is.Take()) { + case ',': + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case ']': + if (!handler.EndArray(elementCount)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + break; + } + } + } + + template + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') { + if (!handler.Null()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + template + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') { + if (!handler.Bool(true)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + template + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') { + if (!handler.Bool(false)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(InputStream& is) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Take(); + codepoint <<= 4; + codepoint += static_cast(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + } + return codepoint; + } + + template + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push() = c; + ++length_; + } + size_t Length() const { return length_; } + Ch* Pop() { + return stack_.template Pop(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head; + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream stackStream(stack_); + ParseStringToStream(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (!success) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const char escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 +//!@endcond + + RAPIDJSON_ASSERT(is.Peek() == '\"'); + is.Take(); // Skip '\"' + + for (;;) { + Ch c = is.Peek(); + if (c == '\\') { // Escape + is.Take(); + Ch e = is.Take(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) { + os.Put(escape[(unsigned char)e]); + } + else if (e == 'u') { // Unicode + unsigned codepoint = ParseHex4(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { + // Handle UTF-16 surrogate pair + if (is.Take() != '\\' || is.Take() != 'u') + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2); + unsigned codepoint2 = ParseHex4(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); + } + else if (c == '"') { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1); + else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); + else { + if (parseFlags & kParseValidateEncodingFlag ? + !Transcoder::Validate(is, os) : + !Transcoder::Transcode(is, os)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); + } + } + } + + template + class NumberStream; + + template + class NumberStream { + public: + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } + RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } + RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const char* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : NumberStream(reader, is), stackStream(reader.stack_) {} + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put((char)Base::is.Peek()); + return Base::is.Take(); + } + + size_t Length() { return stackStream.Length(); } + + const char* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream stackStream; + }; + + template + void ParseNumber(InputStream& is, Handler& handler) { + internal::StreamLocalCopy copy(is); + NumberStream s(*this, copy.s); + + // Parse minus + bool minus = false; + if (s.Peek() == '-') { + minus = true; + s.Take(); + } + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (s.Peek() == '0') { + i = 0; + s.TakePush(); + } + else if (s.Peek() >= '1' && s.Peek() <= '9') { + i = static_cast(s.TakePush() - '0'); + + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 214748364) { // 2^31 = 2147483648 + if (i != 214748364 || s.Peek() > '8') { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 429496729) { // 2^32 - 1 = 4294967295 + if (i != 429496729 || s.Peek() > '5') { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + double d = 0.0; + if (use64bit) { + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808 + if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') { + d = i64; + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615 + if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') { + d = i64; + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0 + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (s.Peek() == '.') { + s.Take(); + decimalPosition = s.Length(); + + if (!(s.Peek() >= '0' && s.Peek() <= '9')) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = (double)i64; +#else + // Use double to store significand in 32-bit architecture + d = use64bit ? (double)i64 : (double)i; +#endif + useDouble = true; + } + + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (d > 0.0) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (s.Peek() == 'e' || s.Peek() == 'E') { + if (!useDouble) { + d = use64bit ? i64 : i; + useDouble = true; + } + s.Take(); + + bool expMinus = false; + if (s.Peek() == '+') + s.Take(); + else if (s.Peek() == '-') { + s.Take(); + expMinus = true; + } + + if (s.Peek() >= '0' && s.Peek() <= '9') { + exp = s.Take() - '0'; + if (expMinus) { + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp >= 214748364) { // Issue #313: prevent overflow exponent + while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp > maxExp) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + } + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + cont = handler.Double(minus ? -d : d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(static_cast(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast(~i + 1)); + else + cont = handler.Uint(i); + } + } + if (!cont) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse any JSON value + template + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull (is, handler); break; + case 't': ParseTrue (is, handler); break; + case 'f': ParseFalse (is, handler); break; + case '"': ParseString(is, handler); break; + case '{': ParseObject(is, handler); break; + case '[': ParseArray (is, handler); break; + default : + ParseNumber(is, handler); + break; + + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingStartState = 0, + IterativeParsingFinishState, + IterativeParsingErrorState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingKeyValueDelimiterState, + IterativeParsingMemberValueState, + IterativeParsingMemberDelimiterState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingElementDelimiterState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState, + + cIterativeParsingStateCount + }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || unsigned(c) < 256) + return (Token)tokenMap[(unsigned char)c]; + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + } + }; // End of G + + return (IterativeParsingState)G[state][token]; + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + + switch (dst) { + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push(1) = n; + // Initialize and push the member/element count. + *stack_.template Push(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top() = *stack_.template Top() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Get member count. + SizeType c = *stack_.template Pop(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Get element count. + SizeType c = *stack_.template Pop(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; + default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return; + } + } + + template + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader, UTF8<> > Reader; + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_READER_H_ diff --git a/contrib/rapidjson/include/rapidjson/stringbuffer.h b/contrib/rapidjson/include/rapidjson/stringbuffer.h new file mode 100644 index 000000000..1c9c80b79 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/stringbuffer.h @@ -0,0 +1,93 @@ +// 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 +// 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_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "rapidjson.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif + + void Put(Ch c) { *stack_.template Push() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop(1); + } + Ch* Push(size_t count) { return stack_.template Push(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); + + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer > StringBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { + std::memset(stream.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/contrib/rapidjson/include/rapidjson/writer.h b/contrib/rapidjson/include/rapidjson/writer.h new file mode 100644 index 000000000..874faa881 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/writer.h @@ -0,0 +1,395 @@ +// 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 +// 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_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include // placement new + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return WriteNull(); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); } + bool Int(int i) { Prefix(kNumberType); return WriteInt(i); } + bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); } + bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + Prefix(kStringType); + return WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + bool ret = WriteEndObject(); + if (level_stack_.Empty()) // end of json text + os_->Flush(); + return ret; + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + bool ret = WriteEndArray(); + if (level_stack_.Empty()) // end of json text + os_->Flush(); + return ret; + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + static const size_t kDefaultLevelDepth = 32; + + bool WriteNull() { + os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e'); + } + else { + os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + for (char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteDouble(double d) { + char buffer[25]; + char* end = internal::dtoa(d, buffer); + for (char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + os_->Put('\"'); + GenericStringStream is(str); + while (is.Tell() < length) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + os_->Put('\\'); + os_->Put('u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + os_->Put(hexDigits[(codepoint >> 12) & 15]); + os_->Put(hexDigits[(codepoint >> 8) & 15]); + os_->Put(hexDigits[(codepoint >> 4) & 15]); + os_->Put(hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + os_->Put(hexDigits[(lead >> 12) & 15]); + os_->Put(hexDigits[(lead >> 8) & 15]); + os_->Put(hexDigits[(lead >> 4) & 15]); + os_->Put(hexDigits[(lead ) & 15]); + os_->Put('\\'); + os_->Put('u'); + os_->Put(hexDigits[(trail >> 12) & 15]); + os_->Put(hexDigits[(trail >> 8) & 15]); + os_->Put(hexDigits[(trail >> 4) & 15]); + os_->Put(hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { + is.Take(); + os_->Put('\\'); + os_->Put(escape[(unsigned char)c]); + if (escape[(unsigned char)c] == 'u') { + os_->Put('0'); + os_->Put('0'); + os_->Put(hexDigits[(unsigned char)c >> 4]); + os_->Put(hexDigits[(unsigned char)c & 0xF]); + } + } + else + if (!Transcoder::Transcode(is, *os_)) + return false; + } + os_->Put('\"'); + return true; + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + void Prefix(Type type) { + (void)type; + if (level_stack_.GetSize() != 0) { // this value is not at root + Level* level = level_stack_.template Top(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + OutputStream* os_; + internal::Stack level_stack_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteDouble(double d) { + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer); + os_->Pop(static_cast(25 - (end - buffer))); + return true; +} + +RAPIDJSON_NAMESPACE_END + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/contrib/rapidjson/license.txt b/contrib/rapidjson/license.txt new file mode 100644 index 000000000..7ccc161c8 --- /dev/null +++ b/contrib/rapidjson/license.txt @@ -0,0 +1,57 @@ +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. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. +A copy of the MIT License is included in this file. + +Other dependencies and licenses: + +Open Source Software Licensed Under the BSD License: +-------------------------------------------------------------------- + +The msinttypes r29 +Copyright (c) 2006-2013 Alexander Chemeris +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Open Source Software Licensed Under the JSON License: +-------------------------------------------------------------------- + +json.org +Copyright (c) 2002 JSON.org +All Rights Reserved. + +JSON_checker +Copyright (c) 2002 JSON.org +All Rights Reserved. + + +Terms of the JSON License: +--------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Terms of the MIT License: +-------------------------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/contrib/rapidjson/readme.md b/contrib/rapidjson/readme.md new file mode 100644 index 000000000..fb270fb96 --- /dev/null +++ b/contrib/rapidjson/readme.md @@ -0,0 +1,129 @@ +![](doc/logo/rapidjson.png) + +![](https://img.shields.io/badge/release-v1.0.2-blue.png) + +## A fast JSON parser/generator for C++ with both SAX/DOM style API + +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. + +* [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) +* RapidJSON Documentation + * [English](http://rapidjson.org/) + * [简体中文](http://rapidjson.org/zh-cn/) + * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference. + +## Build status + +| [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] | +| :---------------: | :-----------------: | :-------------------: | +| ![lin-badge] | ![win-badge] | ![cov-badge] | + +[lin-badge]: https://travis-ci.org/miloyip/rapidjson.png?branch=master "Travis build status" +[lin-link]: https://travis-ci.org/miloyip/rapidjson "Travis build status" +[win-badge]: https://ci.appveyor.com/api/projects/status/u658dcuwxo14a8m9/branch/master "AppVeyor build status" +[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson/branch/master "AppVeyor build status" +[cov-badge]: https://coveralls.io/repos/miloyip/rapidjson/badge.png?branch=master +[cov-link]: https://coveralls.io/r/miloyip/rapidjson?branch=master + +## Introduction + +RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/). + +* RapidJSON is **small** but **complete**. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code. + +* RapidJSON is **fast**. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration. + +* RapidJSON is **self-contained** and **header-only**. It does not depend on external libraries such as BOOST. It even does not depend on STL. + +* RapidJSON is **memory-friendly**. Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing. + +* RapidJSON is **Unicode-friendly**. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character). + +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. More information about JSON can be obtained at +* [Introducing JSON](http://json.org/) +* [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](http://www.ietf.org/rfc/rfc7159.txt) +* [Standard ECMA-404: The JSON Data Interchange Format](http://www.ecma-international.org/publications/standards/Ecma-404.htm) + +## Compatibility + +RapidJSON is cross-platform. Some platform/compiler combinations which have been tested are shown as follows. +* Visual C++ 2008/2010/2013 on Windows (32/64-bit) +* GNU C++ 3.8.x on Cygwin +* Clang 3.4 on Mac OS X (32/64-bit) and iOS +* Clang 3.4 on Android NDK + +Users can build and run the unit tests on their platform/compiler. + +## Installation + +RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path. + +RapidJSON uses following software as its dependencies: +* [CMake](http://www.cmake.org) as a general build tool +* (optional)[Doxygen](http://www.doxygen.org) to build documentation +* (optional)[googletest](https://code.google.com/p/googletest/) for unit and performance testing + +To generate user documentation and run tests please proceed with the steps below: + +1. Execute `git submodule update --init` to get the files of thirdparty submodules (google test). +2. Create directory called `build` in rapidjson source directory. +3. Change to `build` directory and run `cmake ..` command to configure your build. Windows users can do the same with cmake-gui application. +4. On Windows, build the solution found in the build directory. On Linux, run `make` from the build directory. + +On successfull build you will find compiled test and example binaries in `bin` +directory. The generated documentation will be available in `doc/html` +directory of the build tree. To run tests after finished build please run `make +test` or `ctest` from your build tree. You can get detailed output using `ctest +-V` command. + +It is possible to install library system-wide by running `make install` command +from the build tree with administrative privileges. This will install all files +according to system preferences. Once RapidJSON is installed, it is possible +to use it from other CMake projects by adding `find_package(RapidJSON)` line to +your CMakeLists.txt. + +## Usage at a glance + +This simple example parses a JSON string into a document (DOM), make a simple modification of the DOM, and finally stringify the DOM to a JSON string. + +~~~~~~~~~~cpp +// rapidjson/example/simpledom/simpledom.cpp` +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; + +int main() { + // 1. Parse a JSON string into DOM. + const char* json = "{\"project\":\"rapidjson\",\"stars\":10}"; + Document d; + d.Parse(json); + + // 2. Modify it by DOM. + Value& s = d["stars"]; + s.SetInt(s.GetInt() + 1); + + // 3. Stringify the DOM + StringBuffer buffer; + Writer writer(buffer); + d.Accept(writer); + + // Output {"project":"rapidjson","stars":11} + std::cout << buffer.GetString() << std::endl; + return 0; +} +~~~~~~~~~~ + +Note that this example did not handle potential errors. + +The following diagram shows the process. + +![simpledom](doc/diagram/simpledom.png) + +More [examples](https://github.com/miloyip/rapidjson/tree/master/example) are available. From 148a20a703a614424b4b10c34c40f35a8deba495 Mon Sep 17 00:00:00 2001 From: Otger Date: Thu, 26 Nov 2015 02:36:22 +0100 Subject: [PATCH 60/77] Experimental support for glTF --- code/CMakeLists.txt | 11 +- code/ImporterRegistry.cpp | 6 + code/glTFFileData.h | 122 ++++ code/glTFImporter.cpp | 1138 ++++++++++++++++++++++++++++++++++++- code/glTFImporter.h | 32 +- code/glTFUtil.cpp | 164 ++++++ code/glTFUtil.h | 67 +++ 7 files changed, 1509 insertions(+), 31 deletions(-) create mode 100644 code/glTFFileData.h create mode 100644 code/glTFUtil.cpp create mode 100644 code/glTFUtil.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 33de95cb6..9a577fa1b 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -562,9 +562,12 @@ ADD_ASSIMP_IMPORTER(X XFileExporter.cpp ) -ADD_ASSIMP_IMPORTER( glFT - glTFImporter.cpp - glTFImporter.h +ADD_ASSIMP_IMPORTER(GLTF + glTFImporter.cpp + glTFImporter.h + glTFUtil.cpp + glTFUtil.h + glTFFileData.h ) SET( Step_SRCS @@ -654,6 +657,8 @@ SET( picojson_SRCS ) SOURCE_GROUP( picojson FILES ${picojson_SRCS} ) +INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" ) + # VC2010 fixes if(MSVC10) option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF ) diff --git a/code/ImporterRegistry.cpp b/code/ImporterRegistry.cpp index 289587b04..06e8ca822 100644 --- a/code/ImporterRegistry.cpp +++ b/code/ImporterRegistry.cpp @@ -167,6 +167,9 @@ corresponding preprocessor flag to selectively disable formats. #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER # include "FBXImporter.h" #endif +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER +# include "glTFImporter.h" +#endif #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER # include "AssbinLoader.h" #endif @@ -302,6 +305,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER ) out.push_back( new FBXImporter() ); #endif +#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER ) + out.push_back( new glTFImporter() ); +#endif #if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER ) out.push_back( new AssbinImporter() ); #endif diff --git a/code/glTFFileData.h b/code/glTFFileData.h new file mode 100644 index 000000000..2a124d377 --- /dev/null +++ b/code/glTFFileData.h @@ -0,0 +1,122 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef AI_GLTFFILEDATA_H_INC +#define AI_GLTFFILEDATA_H_INC + +#include + +namespace Assimp { +namespace glTF { + + +//! Magic number for GLB files +#define AI_GLB_MAGIC_NUMBER "glTF" + + +#include "./../include/assimp/Compiler/pushpack1.h" + +// KHR_binary_glTF (binary .glb file) +// 20-byte header (+ the JSON + a "body" data section) +struct GLB_Header +{ + //! Magic number: "glTF" + unsigned char magic[4]; // "glTF" + + //! Version number (always 1 as of the last update) + uint32_t version; + + //! Total length of the Binary glTF, including header, scene, and body, in bytes + uint32_t length; + + //! Length, in bytes, of the glTF scene + uint32_t sceneLength; + + //! Specifies the format of the glTF scene (see the SceneFormat enum) + uint32_t sceneFormat; +} PACK_STRUCT; + +#include "./../include/assimp/Compiler/poppack1.h" + + + +//! Values for the GLB_Header::sceneFormat field +enum SceneFormat +{ + SceneFormat_JSON = 0 +}; + + +//! Values for the mesh primitive modes +enum PrimitiveMode +{ + PrimitiveMode_POINTS = 0, + PrimitiveMode_LINES = 1, + PrimitiveMode_LINE_LOOP = 2, + PrimitiveMode_LINE_STRIP = 3, + PrimitiveMode_TRIANGLES = 4, + PrimitiveMode_TRIANGLE_STRIP = 5, + PrimitiveMode_TRIANGLE_FAN = 6 +}; + + +//! Values for the accessors component type field +enum ComponentType +{ + ComponentType_BYTE = 5120, + ComponentType_UNSIGNED_BYTE = 5121, + ComponentType_SHORT = 5122, + ComponentType_UNSIGNED_SHORT = 5123, + ComponentType_FLOAT = 5126 +}; + + +//! Will hold the enabled extensions +struct Extensions +{ + bool KHR_binary_glTF; +}; + + +} // end namespaces +} + + +#endif // AI_GLTFFILEDATA_H_INC + diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 82c5c798a..374556af1 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -42,32 +42,1046 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "DefaultIOSystem.h" #include + #include #include #include #include -#include "../contrib/picojson/picojson.h" +#include "glTFFileData.h" +#include "glTFUtil.h" -namespace Assimp { +#include +#include +#include - static const aiImporterDesc desc = { - "glTF Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour, - 0, - 0, - 0, - 0, - "gltf" - }; +using namespace rapidjson; + +using namespace Assimp; +using namespace Assimp::glTF; + + +using boost::shared_ptr; +using boost::scoped_ptr; + +// (cannot typedef' templated classes, and "using" is c++11) +#define Ptr shared_ptr + +// (used everywhere, and cannot use "auto") +typedef rapidjson::Value::MemberIterator MemIt; + + +// +// JSON Value reading helpers +// + +inline static void Getf(const Value& v, float& out) +{ + if (v.IsNumber()) out = static_cast(v.GetDouble()); +} + +template +struct ReadHelper { }; + +template<> struct ReadHelper { static bool Read(Value& val, int& out) { + return val.IsInt() ? val.GetInt(), true : false; +}}; + +template<> struct ReadHelper { static bool Read(Value& val, unsigned int& out) { + return val.IsInt() ? out = static_cast(val.GetInt()), true : false; +}}; + +template<> struct ReadHelper { static bool Read(Value& val, float& out) { + return val.IsNumber() ? out = static_cast(val.GetDouble()), true : false; +}}; + +template<> struct ReadHelper { static bool Read(Value& val, const char*& out) { + return val.IsString() ? out = val.GetString(), true : false; +}}; + +template<> struct ReadHelper { static bool Read(Value& val, std::string& out) { + return val.IsString() ? out = val.GetString(), true : false; +}}; + +template<> struct ReadHelper { static bool Read(Value& v, aiColor3D& out) { + if (!v.IsArray() || v.Size() < 3) return false; + Getf(v[0], out.r); Getf(v[1], out.g); Getf(v[2], out.b); + return true; +}}; + +template<> struct ReadHelper { static bool Read(Value& v, aiVector3D& out) { + if (!v.IsArray() || v.Size() != 3) return false; + Getf(v[0], out.x); Getf(v[1], out.y); Getf(v[2], out.z); + return true; +}}; + +template<> struct ReadHelper { static bool Read(Value& v, aiQuaternion& out) { + if (!v.IsArray() || v.Size() != 4) return false; + Getf(v[0], out.x); Getf(v[1], out.y); Getf(v[2], out.z); Getf(v[3], out.w); + return true; +}}; + +template<> struct ReadHelper { static bool Read(Value& v, aiMatrix4x4& o) { + if (!v.IsArray() || v.Size() != 16) return false; + Getf(v[ 0], o.a1); Getf(v[ 1], o.b1); Getf(v[ 2], o.c1); Getf(v[ 3], o.d1); + Getf(v[ 4], o.a2); Getf(v[ 5], o.b2); Getf(v[ 6], o.c2); Getf(v[ 7], o.d2); + Getf(v[ 8], o.a3); Getf(v[ 9], o.b3); Getf(v[10], o.c3); Getf(v[11], o.d3); + Getf(v[12], o.a4); Getf(v[13], o.b4); Getf(v[14], o.c4); Getf(v[15], o.d4); + return true; +}}; + +template +inline static bool Read(Value& val, T& out) +{ + return ReadHelper::Read(val, out); +} + +template +inline static bool ReadMember(Value& obj, const char* id, T& out) +{ + MemIt it = obj.FindMember(id); + if (it != obj.MemberEnd()) { + return ReadHelper::Read(it->value, out); + } + return false; +} + +template +inline static T TryReadMember(Value& obj, const char* id, T defaultValue) +{ + T out; + return ReadMember(obj, id, out) ? out : defaultValue; +} + + +//! References a sequence of loaded elements (e.g. meshes) +typedef std::pair Range; + + + +// +// glTFReader class +// + +class glTFReader; + +//! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID +template +class LazyDict +{ + typedef typename std::gltf_unordered_map Map; + + Value* mDict; //! JSON dictionary object + const char* mDictId; //! ID of the dictionary object + glTFReader& mInstance; //! The glTFReader instance + Map mReadObjs; //! The read objects + +public: + LazyDict(glTFReader& instance, const char* dictId) + : mDictId(dictId), mInstance(instance) + { + Document& doc = mInstance.GetDocument(); + + MemIt it = doc.FindMember(dictId); + mDict = (it != doc.MemberEnd() && it->value.IsObject()) ? &it->value : nullptr; + } + + T Get(const char* id) + { + if (!mDict) return T(); // section was missing + + Map::iterator it = mReadObjs.find(id); + if (it != mReadObjs.end()) { // already created? + return it->second; + } + + // read it from the JSON object + MemIt obj = mDict->FindMember(id); + if (obj == mDict->MemberEnd()) { + throw DeadlyImportError("Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\""); + } + + // create an instance of the given type + T val = (mInstance.*FACTORY_FN)(id, obj->value); + mReadObjs[id] = val; + return val; + } +}; + +struct Buffer; +struct BufferView; +struct Accessor; + +struct Image; +struct Texture; + +//! Handles the reading of the glTF JSON document +class glTFReader +{ + aiScene* mScene; + Document& mDoc; + IOSystem& mIO; + + // Vectors of imported objects, will be copied to mScene + std::vector mImpMaterials; + std::vector mImpMeshes; + std::vector mImpTextures; + + Extensions mExtensions; + + Ptr mBodyBuffer; //! Special buffer containing the body data + + + Ptr LoadBuffer(const char* id, Value& obj); + Ptr LoadBufferView(const char* id, Value& obj); + Ptr LoadAccessor(const char* id, Value& obj); + + Ptr LoadImage(const char* id, Value& obj); + Ptr LoadTexture(const char* id, Value& obj); + + aiNode* LoadNode(const char* id, Value& node); + Range LoadMesh(const char* id, Value& mesh); + unsigned int LoadMaterial(const char* id, Value& material); + + typedef glTFReader T; // (to shorten next declarations) + + LazyDict, &T::LoadAccessor> mAccessors; + //LazyDict mAnimations; + //LazyDict mAssets; + LazyDict, &T::LoadBuffer> mBuffers; + LazyDict, &T::LoadBufferView> mBufferViews; + //LazyDict mCameras; + LazyDict, &T::LoadImage> mImages; + LazyDict mMaterials; + LazyDict mMeshes; + LazyDict mNodes; + //LazyDict, &T::LoadProgram> mPrograms; + //LazyDict, &T::LoadSampler> mSamplers; + //LazyDict, &T::LoadShader> mShaders; + //LazyDict, &T::LoadSkin> mSkins; + //LazyDict,&T::LoadTechnique> mTechniques; + LazyDict, &T::LoadTexture> mTextures; + + + void LoadScene(Value& scene) + { + MemIt nodesm = scene.FindMember("nodes"); + if (nodesm != scene.MemberEnd() && nodesm->value.IsArray()) { + Value& nodes = nodesm->value; + + unsigned int numRootNodes = nodes.Size(); + if (numRootNodes == 1) { // a single root node: use it + if (nodes[0].IsString()) { + mScene->mRootNode = mNodes.Get(nodes[0].GetString()); + } + } + else if (numRootNodes > 1) { // more than one root node: create a fake root + aiNode* root = new aiNode("ROOT"); + root->mChildren = new aiNode*[numRootNodes]; + for (unsigned int i = 0; i < numRootNodes; ++i) { + if (nodes[i].IsString()) { + aiNode* node = mNodes.Get(nodes[i].GetString()); + if (node) { + node->mParent = root; + root->mChildren[root->mNumChildren++] = node; + } + } + } + mScene->mRootNode = root; + } + } + } + + void SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType, + const char* pKey, unsigned int type, unsigned int idx); + + void CopyData() + { + // TODO: it does not split the loaded vertices, should it? + mScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; + + if (mImpMaterials.empty()) { + mImpMaterials.push_back(new aiMaterial()); + } + + if (mImpMaterials.size()) { + mScene->mNumMaterials = mImpMaterials.size(); + mScene->mMaterials = new aiMaterial*[mImpMaterials.size()]; + std::swap_ranges(mImpMaterials.begin(), mImpMaterials.end(), mScene->mMaterials); + } + + if (mImpMeshes.size()) { + mScene->mNumMeshes = mImpMeshes.size(); + mScene->mMeshes = new aiMesh*[mImpMeshes.size()]; + std::swap_ranges(mImpMeshes.begin(), mImpMeshes.end(), mScene->mMeshes); + } + + if (mImpTextures.size()) { + mScene->mNumTextures = mImpTextures.size(); + mScene->mTextures = new aiTexture*[mImpTextures.size()]; + std::swap_ranges(mImpTextures.begin(), mImpTextures.end(), mScene->mTextures); + } + } + +public: + glTFReader(aiScene* scene, Document& document, IOSystem& iohandler, shared_ptr& bodyBuff) : + mScene(scene), + mDoc(document), + mIO(iohandler), + mBodyBuffer(bodyBuff), + mAccessors(*this, "accessors"), + //mAnimations(*this, "animations"), + //mAssets(*this, "assets"), + mBuffers(*this, "buffers"), + mBufferViews(*this, "bufferViews"), + //mCameras(*this, "cameras"), + mImages(*this, "images"), + mMaterials(*this, "materials"), + mMeshes(*this, "meshes"), + mNodes(*this, "nodes"), + //mPrograms(*this, "programs"), + //mSamplers(*this, "samplers"), + //mShaders(*this, "shaders"), + //mSkins(*this, "skins"), + //mTechniques(*this, "techniques"), + mTextures(*this, "textures") + { + memset(&mExtensions, 0, sizeof(mExtensions)); + } + + Document& GetDocument() + { + return mDoc; + } + + //! Main function + void Load() + { + // read the used extensions + MemIt extensionsUsed = mDoc.FindMember("extensionsUsed"); + if (extensionsUsed != mDoc.MemberEnd() && extensionsUsed->value.IsArray()) { + std::gltf_unordered_map exts; + + for (unsigned int i = 0; i < extensionsUsed->value.Size(); ++i) { + if (extensionsUsed->value[i].IsString()) { + exts[extensionsUsed->value[i].GetString()] = true; + } + } + + if (exts.find("KHR_binary_glTF") != exts.end()) { + mExtensions.KHR_binary_glTF = true; + } + } + + + const char* sceneId = 0; + + // the "scene" property specifies which scene to load + { + MemIt scene = mDoc.FindMember("scene"); + if (scene != mDoc.MemberEnd() && scene->value.IsString()) { + sceneId = scene->value.GetString(); + } + } + + MemIt scene; + + MemIt scenes = mDoc.FindMember("scenes"); + if (scenes != mDoc.MemberEnd() && scenes->value.IsObject()) { + if (sceneId) { + scene = scenes->value.FindMember(sceneId); + if (scene == scenes->value.MemberEnd()) { + //ThrowException("Missing scene!"); + } + } + else { // if not specified, use the first one + scene = scenes->value.MemberBegin(); + } + } + + if (scene != scenes->value.MemberEnd()) { + LoadScene(scene->value); + } + + CopyData(); + } +}; + +struct Buffer +{ +private: + std::size_t byteLength; + shared_ptr data; + +public: + Buffer(shared_ptr& d, std::size_t length) + : data(d), byteLength(length) + { } + + std::size_t GetLength() const + { + return byteLength; + } + + uint8_t* GetPointer() + { + return data.get(); + } + + static Buffer* FromStream(IOStream& stream, std::size_t length = 0, std::size_t baseOffset = 0) + { + if (!length) { + length = stream.FileSize(); + } + + if (baseOffset) { + stream.Seek(baseOffset, aiOrigin_SET); + } + + shared_ptr data(new uint8_t[length]); + + + if (stream.Read(data.get(), length, 1) != 1) { + throw DeadlyImportError("Unable to load buffer from file!"); + } + + return new Buffer(data, length); + } +}; + + +Ptr glTFReader::LoadBuffer(const char* id, Value& obj) +{ + if (!obj.IsObject()) return Ptr(); + + if (mExtensions.KHR_binary_glTF && strcmp(id, "KHR_binary_glTF") == 0) { + return mBodyBuffer; + } + else { + const char* uri = TryReadMember(obj, "uri", 0); + + Buffer* b = 0; + if (IsDataURI(uri)) { + const char* comma = strchr(uri, ','); + *const_cast(comma) = '\0'; + + bool isBase64 = (strstr(uri, "base64") != 0); + if (isBase64) { + uint8_t* data; + std::size_t dataLen = DecodeBase64(comma + 1, data); + b = new Buffer(shared_ptr(data), dataLen); + } + } + else if (uri) { // Local file + unsigned int byteLength = TryReadMember(obj, "byteLength", 0u); + + scoped_ptr file(mIO.Open(uri)); + b = Buffer::FromStream(*file.get(), byteLength); + } + return Ptr(b); + } +} + + +struct BufferView +{ + Ptr buffer; + unsigned int byteOffset; + unsigned int byteLength; + + BufferView() {} + + BufferView(Value& obj) + { + Read(obj); + } + + void Read(Value& obj) + { + if (!obj.IsObject()) return; + + } + +}; + +Ptr glTFReader::LoadBufferView(const char* id, Value& obj) +{ + if (!obj.IsObject()) return Ptr(); + + + const char* bufferId = TryReadMember(obj, "buffer", 0); + if (!bufferId) return Ptr(); + + BufferView* bv = new BufferView(); + + bv->buffer = mBuffers.Get(bufferId); + bv->byteOffset = TryReadMember(obj, "byteOffset", 0u); + bv->byteLength = TryReadMember(obj, "byteLength", 0u); + + return Ptr(bv); +} + + +struct Accessor +{ + Ptr bufferView; + unsigned int byteOffset; + unsigned int byteStride; + ComponentType componentType; + unsigned int count; + std::string type; // "SCALAR", "VEC2", "VEC3", "VEC4", "MAT2", "MAT3", "MAT4" + //unsigned int max; + ///unsigned int min; + + unsigned int numComponents; + unsigned int bytesPerComponent; + unsigned int elemSize; + + uint8_t* data; + + inline uint8_t* GetPointer() + { + if (!bufferView || !bufferView->buffer) return 0; + + std::size_t offset = byteOffset + bufferView->byteOffset; + return bufferView->buffer->GetPointer() + offset; + } + + template + void ExtractData(T*& outData, unsigned int* outCount = 0, unsigned int* outComponents = 0) + { + if (!data) return; + + const std::size_t totalSize = elemSize * count; + + const std::size_t targetElemSize = sizeof(T); + ai_assert(elemSize <= targetElemSize); + + outData = new T[count]; + if (byteStride == elemSize && targetElemSize == elemSize) { + memcpy(outData, data, totalSize); + } + else { + for (std::size_t i = 0; i < count; ++i) { + memcpy(outData + i, data + i*byteStride, elemSize); + } + } + + if (outCount) *outCount = count; + if (outComponents) *outComponents = numComponents; + } + + template + T GetValue(int i) + { + T value = T(); + memcpy(&value, data + i*byteStride, elemSize); + //value >>= 8 * (sizeof(T) - elemSize); + return value; + } +}; + +Ptr glTFReader::LoadAccessor(const char* id, Value& obj) +{ + if (!obj.IsObject()) return Ptr(); + + Accessor* a = new Accessor(); + + const char* bufferViewId = TryReadMember(obj, "bufferView", 0); + if (bufferViewId) { + a->bufferView = mBufferViews.Get(bufferViewId); + } + + int compType = TryReadMember(obj, "componentType", unsigned(ComponentType_BYTE)); + + a->byteOffset = TryReadMember(obj, "byteOffset", 0u); + a->byteStride = TryReadMember(obj, "byteStride", 0u); + a->componentType = static_cast(compType); + a->count = TryReadMember(obj, "count", 0u); + a->type = TryReadMember(obj, "type", ""); + + a->numComponents = 1; // "SCALAR" + if (a->type == "VEC2") a->numComponents = 2; + else if (a->type == "VEC3") a->numComponents = 3; + else if (a->type == "VEC4") a->numComponents = 4; + else if (a->type == "MAT2") a->numComponents = 4; + else if (a->type == "MAT3") a->numComponents = 9; + else if (a->type == "MAT4") a->numComponents = 16; + + switch (a->componentType) { + case ComponentType_SHORT: + case ComponentType_UNSIGNED_SHORT: + a->bytesPerComponent = 2; + break; + + case ComponentType_FLOAT: + a->bytesPerComponent = 4; + break; + + //case Accessor::ComponentType_BYTE: + //case Accessor::ComponentType_UNSIGNED_BYTE: + default: + a->bytesPerComponent = 1; + } + + a->elemSize = a->numComponents * a->bytesPerComponent; + if (!a->byteStride) a->byteStride = a->elemSize; + + a->data = a->GetPointer(); + + return Ptr(a); +} + +static inline void setFace(aiFace& face, int a) +{ + face.mNumIndices = 1; + face.mIndices = new unsigned int[1]; + face.mIndices[0] = a; +} + +static inline void setFace(aiFace& face, int a, int b) +{ + face.mNumIndices = 2; + face.mIndices = new unsigned int[2]; + face.mIndices[0] = a; + face.mIndices[1] = b; +} + +static inline void setFace(aiFace& face, int a, int b, int c) +{ + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + face.mIndices[0] = a; + face.mIndices[1] = b; + face.mIndices[2] = c; +} + +Range glTFReader::LoadMesh(const char* id, Value& mesh) +{ + Range range; + range.first = mImpMeshes.size(); + range.second = mImpMeshes.size(); + + MemIt primitives = mesh.FindMember("primitives"); + if (primitives != mesh.MemberEnd() && primitives->value.IsArray()) { + for (unsigned int i = 0; i < primitives->value.Size(); ++i) { + Value& primitive = primitives->value[i]; + + aiMesh* aimesh = new aiMesh(); + mImpMeshes.push_back(aimesh); + ++range.second; + + MemIt mode = primitive.FindMember("mode"); + if (mode != primitive.MemberEnd() && mode->value.IsInt()) { + switch (mode->value.GetInt()) { + case PrimitiveMode_POINTS: + aimesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + + case PrimitiveMode_LINES: + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: + aimesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + + case PrimitiveMode_TRIANGLES: + case PrimitiveMode_TRIANGLE_STRIP: + case PrimitiveMode_TRIANGLE_FAN: + aimesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + } + } + + MemIt attrs = primitive.FindMember("attributes"); + if (attrs != primitive.MemberEnd() && attrs->value.IsObject()) { + for (MemIt it = attrs->value.MemberBegin(); it != attrs->value.MemberEnd(); ++it) { + if (!it->value.IsString()) continue; + const char* attr = it->name.GetString(); + const char* accessorId = it->value.GetString(); + + Ptr accessor = mAccessors.Get(accessorId); + if (!accessor) continue; + + if (strcmp(attr, "POSITION") == 0) { + accessor->ExtractData(aimesh->mVertices, &aimesh->mNumVertices); + } + else if (strcmp(attr, "NORMAL") == 0) { + accessor->ExtractData(aimesh->mNormals); + } + else if (strncmp(attr, "TEXCOORD_", 9) == 0) { + int idx = attr[9] - '0'; + accessor->ExtractData(aimesh->mTextureCoords[idx], 0, &aimesh->mNumUVComponents[idx]); + } + } + } + + MemIt indices = primitive.FindMember("indices"); + if (indices != primitive.MemberEnd() && indices->value.IsString()) { + Ptr acc = mAccessors.Get(indices->value.GetString()); + if (acc) { + aiFace* faces = 0; + std::size_t nFaces = 0; + + int primitiveMode = mode->value.GetInt(); + switch (primitiveMode) { + case PrimitiveMode_POINTS: { + nFaces = acc->count; + faces = new aiFace[nFaces]; + for (unsigned i = 0; i < acc->count; ++i) { + setFace(faces[i], acc->GetValue(i)); + } + break; + } + + case PrimitiveMode_LINES: { + nFaces = acc->count / 2; + faces = new aiFace[nFaces]; + for (unsigned i = 0; i < acc->count; i += 2) { + setFace(faces[i / 2], acc->GetValue(i), acc->GetValue(i + 1)); + } + break; + } + + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = acc->count - ((primitiveMode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + faces = new aiFace[nFaces]; + setFace(faces[0], acc->GetValue(0), acc->GetValue(1)); + for (unsigned i = 2; i < acc->count; ++i) { + setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetValue(i)); + } + if (primitiveMode == PrimitiveMode_LINE_LOOP) { // close the loop + setFace(faces[acc->count - 1], faces[acc->count - 2].mIndices[1], faces[0].mIndices[0]); + } + break; + } + + case PrimitiveMode_TRIANGLES: { + nFaces = acc->count / 3; + faces = new aiFace[nFaces]; + for (unsigned i = 0; i < acc->count; i += 3) { + setFace(faces[i / 3], acc->GetValue(i), acc->GetValue(i + 1), acc->GetValue(i + 2)); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = acc->count - 2; + faces = new aiFace[nFaces]; + setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2)); + for (unsigned i = 3; i < acc->count; ++i) { + setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetValue(i)); + } + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = acc->count - 2; + faces = new aiFace[nFaces]; + setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2)); + for (unsigned i = 3; i < acc->count; ++i) { + setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetValue(i)); + } + break; + } + + if (faces) { + aimesh->mFaces = faces; + aimesh->mNumFaces = nFaces; + } + } + } + + + MemIt material = primitive.FindMember("material"); + if (material != primitive.MemberEnd() && material->value.IsString()) { + aimesh->mMaterialIndex = mMaterials.Get(material->value.GetString()); + } + } + } + + return range; +} + + +struct Image +{ + aiString uri; +}; + +struct Texture +{ + Ptr source; +}; + +Ptr glTFReader::LoadImage(const char* id, Value& obj) +{ + + Image* img = new Image(); + + std::size_t embeddedDataLen = 0; + uint8_t* embeddedData = 0; + const char* mimeType = 0; + + // Check for extensions first (to detect binary embedded data) + MemIt extensions = obj.FindMember("extensions"); + if (extensions != obj.MemberEnd()) { + Value& exts = extensions->value; + + MemIt KHR_binary_glTF = exts.FindMember("KHR_binary_glTF"); + if (KHR_binary_glTF != exts.MemberEnd() && KHR_binary_glTF->value.IsObject()) { + + int width = TryReadMember(KHR_binary_glTF->value, "width", 0); + int height = TryReadMember(KHR_binary_glTF->value, "height", 0); + + ReadMember(KHR_binary_glTF->value, "mimeType", mimeType); + + const char* bufferViewId; + if (ReadMember(KHR_binary_glTF->value, "bufferView", bufferViewId)) { + Ptr bv = mBufferViews.Get(bufferViewId); + if (bv) { + embeddedDataLen = bv->byteLength; + embeddedData = new uint8_t[embeddedDataLen]; + memcpy(embeddedData, bv->buffer->GetPointer() + bv->byteOffset, embeddedDataLen); + } + } + } + } + + if (!embeddedDataLen) { + const char* uri; + if (ReadMember(obj, "uri", uri)) { + if (IsDataURI(uri)) { + const char* comma = strchr(uri, ','); + *const_cast(comma) = '\0'; + + bool isBase64 = (strstr(uri, "base64") != 0); + if (isBase64) { + embeddedDataLen = DecodeBase64(comma + 1, embeddedData); + } + + const char* sc = strchr(uri, ';'); + if (sc != 0) { + *const_cast(sc) = '\0'; + mimeType = uri; + } + } + else { + img->uri = uri; + } + } + } + + // Add the embedded texture + if (embeddedDataLen > 0) { + aiTexture* tex = new aiTexture(); + mImpTextures.push_back(tex); + + tex->mWidth = static_cast(embeddedDataLen); + tex->mHeight = 0; + tex->pcData = reinterpret_cast(embeddedData); + + if (mimeType) { + const char* ext = strchr(mimeType, '/') + 1; + if (ext) { + if (strcmp(ext, "jpeg") == 0) ext = "jpg"; + + std::size_t len = strlen(ext); + if (len <= 3) { + strcpy(tex->achFormatHint, ext); + } + } + } + + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) + img->uri.data[0] = '*'; + img->uri.length = 1 + ASSIMP_itoa10(img->uri.data + 1, MAXLEN - 1, mImpTextures.size() - 1); + } + + return Ptr(img); +} + +Ptr glTFReader::LoadTexture(const char* id, Value& obj) +{ + Texture* tex = new Texture(); + + const char* source; + if (ReadMember(obj, "source", source)) { + tex->source = mImages.Get(source); + } + + return Ptr(tex); +} + +void glTFReader::SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) +{ + MemIt prop = vals.FindMember(propName); + if (prop != vals.MemberEnd()) { + aiColor3D col; + if (Read(prop->value, col)) { + mat->AddProperty(&col, 1, pKey, type, idx); + } + else if (prop->value.IsString()) { + Ptr tex = mTextures.Get(prop->value.GetString()); + if (tex && tex->source) { + mat->AddProperty(&tex->source->uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); + } + } + } +} + +unsigned int glTFReader::LoadMaterial(const char* id, Value& material) +{ + aiMaterial* mat = new aiMaterial(); + mImpMaterials.push_back(mat); + + const char* name; + if (ReadMember(material, "name", name)) { + aiString str(name); + mat->AddProperty(&str, AI_MATKEY_NAME); + } + + MemIt values = material.FindMember("values"); + if (values != material.MemberEnd() && values->value.IsObject()) { + Value& vals = values->value; + + SetMaterialColorProperty(mat, vals, "diffuse", aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialColorProperty(mat, vals, "specular", aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); + SetMaterialColorProperty(mat, vals, "ambient", aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + + float shininess; + if (ReadMember(vals, "shininess", shininess)) { + mat->AddProperty(&shininess, 1, AI_MATKEY_SHININESS); + } + } + + MemIt extensions = material.FindMember("values"); + if (extensions != material.MemberEnd() && extensions->value.IsObject()) { + Value& exts = extensions->value; + + MemIt KHR_materials_common = exts.FindMember("KHR_materials_common"); + if (KHR_materials_common != exts.MemberEnd() && KHR_materials_common->value.IsObject()) { + // TODO: support KHR_materials_common (https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_common) + } + } + + return static_cast(mImpMaterials.size() - 1); +} + +aiNode* glTFReader::LoadNode(const char* id, Value& node) +{ + aiNode* ainode = new aiNode(id); + + //MemIt name = node.FindMember("name"); + //if (name != node.MemberEnd() && name->value.IsString()) { + // strcpy(ainode->mName.data, name->value.GetString()); + //} + + MemIt children = node.FindMember("children"); + if (children != node.MemberEnd() && children->value.IsArray()) { + + ainode->mChildren = new aiNode*[children->value.Size()]; + //ainode->mNumChildren = 0; + + for (unsigned int i = 0; i < children->value.Size(); ++i) { + Value& child = children->value[i]; + if (child.IsString()) { + // get/create the child node + aiNode* aichild = mNodes.Get(child.GetString()); + aichild->mParent = ainode; + ainode->mChildren[ainode->mNumChildren++] = aichild; + } + } + } + + aiMatrix4x4& transf = ainode->mTransformation; + + MemIt matrix = node.FindMember("matrix"); + if (matrix != node.MemberEnd()) { + Read(matrix->value, transf); + } + else { + MemIt translation = node.FindMember("translation"); + if (translation != node.MemberEnd()) { + aiVector3D trans; + if (Read(matrix->value, trans)) { + aiMatrix4x4 m; + aiMatrix4x4::Translation(trans, m); + transf = m * transf; + } + } + + MemIt scale = node.FindMember("scale"); + if (scale != node.MemberEnd()) { + aiVector3D scal(1.f); + if (Read(matrix->value, scal)) { + aiMatrix4x4 m; + aiMatrix4x4::Scaling(scal, m); + transf = m * transf; + } + } + + MemIt rotation = node.FindMember("rotation"); + if (rotation != node.MemberEnd()) { + aiQuaternion rot; + if (Read(matrix->value, rot)) { + transf = aiMatrix4x4(rot.GetMatrix()) * transf; + } + } + } + + MemIt meshes = node.FindMember("meshes"); + if (meshes != node.MemberEnd() && meshes->value.IsArray()) { + std::size_t numMeshes = (std::size_t)meshes->value.Size(); + + std::vector meshList; + + for (std::size_t i = 0; i < numMeshes; ++i) { + if (meshes->value[i].IsString()) { + Range range = mMeshes.Get(meshes->value[i].GetString()); + for (unsigned int m = range.first; m < range.second; ++m) { + meshList.push_back(m); + } + } + } + + if (meshList.size()) { + ainode->mNumMeshes = meshList.size(); + ainode->mMeshes = new unsigned int[meshList.size()]; + std::swap_ranges(meshList.begin(), meshList.end(), ainode->mMeshes); + } + } + + // TODO load "skeletons", "skin", "jointName", "camera" + + return ainode; +} + + + + + +// +// glTFImporter methods +// + +template<> const std::string LogFunctions::log_prefix = "glTF: "; + +static const aiImporterDesc desc = { + "glTF Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour + | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + 0, + 0, + 0, + 0, + "gltf glb" +}; glTFImporter::glTFImporter() : BaseImporter() -, m_scene( NULL ) -, m_buffer() { +{ } @@ -76,6 +1090,10 @@ glTFImporter::~glTFImporter() { } bool glTFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const { + const std::string& extension = GetExtension(pFile); + if (extension == "gltf" || extension == "glb") { + return true; + } return false; } @@ -83,18 +1101,88 @@ const aiImporterDesc* glTFImporter::GetInfo() const { return &desc; } -void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) { - m_scene = pScene; - boost::shared_ptr stream( pIOHandler->Open( pFile, "rb" ) ); - if (!stream.get()) { - throw DeadlyImportError( "Failed to open file " + pFile + "." ); +void glTFImporter::ReadBinaryHeader(IOStream& stream) +{ + GLB_Header header; + if (stream.Read(&header, sizeof(header), 1) != 1) { + ThrowException("Unable to read the file header"); } - // Get the file-size and validate it, throwing an exception when fails - size_t fileSize = stream->FileSize(); + if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) { + ThrowException("Invalid binary glTF file"); + } - // Allocate buffer and read file into it - TextFileToBuffer( stream.get(), m_buffer ); + AI_SWAP4(header.version); + if (header.version != 1) { + ThrowException("Unsupported binary glTF version"); + } + + AI_SWAP4(header.sceneFormat); + if (header.sceneFormat != SceneFormat_JSON) { + ThrowException("Unsupported binary glTF scene format"); + } + + AI_SWAP4(header.length); + AI_SWAP4(header.sceneLength); + + mSceneLength = static_cast(header.sceneLength); + + mBodyOffset = sizeof(header) + mSceneLength; + mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4 + + mBodyLength = header.length - mBodyOffset; } +void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) { + scoped_ptr stream(pIOHandler->Open(pFile, "rb")); + if (!stream) { + ThrowException("Could not open file for reading"); + } + + // is binary? then read the header + if (GetExtension(pFile) == "glb") { + ReadBinaryHeader(*stream); + } + else { + mSceneLength = stream->FileSize(); + mBodyLength = 0; + } + + + // read the scene data + + scoped_ptr sceneData = new char[mSceneLength + 1]; + sceneData[mSceneLength] = '\0'; + + if (stream->Read(sceneData, 1, mSceneLength) != mSceneLength) { + ThrowException("Could not read the file contents"); + } + + + // parse the JSON document + + Document doc; + doc.ParseInsitu(sceneData); + + if (doc.HasParseError()) { + char buffer[32]; + ASSIMP_itoa10(buffer, doc.GetErrorOffset()); + ThrowException(std::string("JSON parse error, offset ") + buffer + ": " + + GetParseError_En(doc.GetParseError())); + } + + if (!doc.IsObject()) { + ThrowException("gltf file must be a JSON object!"); + } + + + // Buffer instance for the current file embedded contents + shared_ptr bodyBuffer; + if (mBodyLength > 0) { + bodyBuffer.reset(Buffer::FromStream(*stream, mBodyLength, mBodyOffset)); + } + + // import the data + glTFReader reader(pScene, doc, *pIOHandler, bodyBuffer); + reader.Load(); } diff --git a/code/glTFImporter.h b/code/glTFImporter.h index dc113c003..9254040c1 100644 --- a/code/glTFImporter.h +++ b/code/glTFImporter.h @@ -41,10 +41,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_GLTFIMPORTER_H_INC #include "BaseImporter.h" +#include "LogAux.h" +#include "DefaultIOSystem.h" + +#if _MSC_VER > 1500 || (defined __GNUC___) +# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP +# else +# define gltf_unordered_map map +# define gltf_unordered_multimap multimap +#endif + +#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP +# include +# if _MSC_VER > 1600 +# define gltf_unordered_map unordered_map +# define gltf_unordered_multimap unordered_multimap +# else +# define gltf_unordered_map tr1::unordered_map +# define gltf_unordered_multimap tr1::unordered_multimap +# endif +#endif namespace Assimp { -class glTFImporter : public BaseImporter { +/** + * Load the glTF format. + * https://github.com/KhronosGroup/glTF/tree/master/specification + */ +class glTFImporter : public BaseImporter, public LogFunctions { public: glTFImporter(); virtual ~glTFImporter(); @@ -55,8 +79,10 @@ protected: virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ); private: - aiScene *m_scene; - std::vector m_buffer; + void ReadBinaryHeader(IOStream& stream); + + std::size_t mSceneLength; + std::size_t mBodyOffset, mBodyLength; }; } // Namespace assimp diff --git a/code/glTFUtil.cpp b/code/glTFUtil.cpp new file mode 100644 index 000000000..46ef32a42 --- /dev/null +++ b/code/glTFUtil.cpp @@ -0,0 +1,164 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#include "glTFUtil.h" + + +using namespace Assimp; +using namespace Assimp::glTF; + + +bool Assimp::glTF::IsDataURI(const char* uri) +{ + return strncmp(uri, "data:", 5) == 0; +} + + +static const uint8_t tableDecodeBase64[128] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static inline char EncodeCharBase64(uint8_t b) +{ + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[b]; +} + +static inline uint8_t DecodeCharBase64(char c) +{ + return tableDecodeBase64[c]; // TODO faster with lookup table or ifs? + /*if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + return c == '+' ? 62 : 63;*/ +} + +std::size_t Assimp::glTF::DecodeBase64( + const char* in, uint8_t*& out) +{ + return DecodeBase64(in, strlen(in), out); +} + +std::size_t Assimp::glTF::DecodeBase64( + const char* in, std::size_t inLength, uint8_t*& out) +{ + ai_assert(dataLen % 4 == 0); + + if (inLength < 4) { + out = 0; + return 0; + } + + int nEquals = int(in[inLength - 1] == '=') + + int(in[inLength - 2] == '='); + + std::size_t outLength = (inLength * 3) / 4 - nEquals; + out = new uint8_t[outLength]; + memset(out, 0, outLength); + + std::size_t j = 0; + + for (std::size_t i = 0; i < inLength; i += 4) { + uint8_t b0 = DecodeCharBase64(in[i]); + uint8_t b1 = DecodeCharBase64(in[i + 1]); + uint8_t b2 = DecodeCharBase64(in[i + 2]); + uint8_t b3 = DecodeCharBase64(in[i + 3]); + + out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4)); + out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2)); + out[j++] = (uint8_t)((b2 << 6) | b3); + } + + return outLength; +} + + + +void Assimp::glTF::EncodeBase64( + const uint8_t* in, std::size_t inLength, + std::string& out) +{ + std::size_t outLength = ((inLength + 2) / 3) * 4; + + out.resize(outLength); + + std::size_t j = 0; + for (std::size_t i = 0; i < inLength; i += 3) { + uint8_t b = (in[i] & 0xFC) >> 2; + out[j++] = EncodeCharBase64(b); + + b = (in[i] & 0x03) << 4; + if (i + 1 < inLength) { + b |= (in[i + 1] & 0xF0) >> 4; + out[j++] = EncodeCharBase64(b); + + b = (in[i + 1] & 0x0F) << 2; + if (i + 2 < inLength) { + b |= (in[i + 2] & 0xC0) >> 6; + out[j++] = EncodeCharBase64(b); + + b = in[i + 2] & 0x3F; + out[j++] = EncodeCharBase64(b); + } + else { + out[j++] = EncodeCharBase64(b); + out[j++] = '='; + } + } + else { + out[j++] = EncodeCharBase64(b); + out[j++] = '='; + out[j++] = '='; + } + } +} diff --git a/code/glTFUtil.h b/code/glTFUtil.h new file mode 100644 index 000000000..010d50ee3 --- /dev/null +++ b/code/glTFUtil.h @@ -0,0 +1,67 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef AI_GLTFUTIL_H_INC +#define AI_GLTFUTIL_H_INC + +//#include "StreamReader.h" +//#include "MemoryIOWrapper.h" +#include "StringComparison.h" + +namespace Assimp { +namespace glTF { + + // + // Misc + // + + std::size_t DecodeBase64(const char* in, uint8_t*& out); + std::size_t DecodeBase64(const char* in, std::size_t inLength, uint8_t*& out); + + void EncodeBase64(const uint8_t* in, std::size_t inLength, std::string& out); + + + bool IsDataURI(const char* uri); + +} +} + + +#endif // AI_GLTFUTIL_H_INC + From 502d9f17b6d58f81877876ab8865e26b5a524e3c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 26 Nov 2015 20:49:00 +0100 Subject: [PATCH 61/77] glTF: add importer to registry and try to parse json. --- code/ImporterRegistry.cpp | 10 +++++++--- code/glTFImporter.cpp | 37 ++++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/code/ImporterRegistry.cpp b/code/ImporterRegistry.cpp index 289587b04..f8382bcdc 100644 --- a/code/ImporterRegistry.cpp +++ b/code/ImporterRegistry.cpp @@ -170,7 +170,9 @@ corresponding preprocessor flag to selectively disable formats. #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER # include "AssbinLoader.h" #endif - +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER +# include "glTFImporter.h" +#endif #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER # include "C4DImporter.h" #endif @@ -305,8 +307,10 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) #if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER ) out.push_back( new AssbinImporter() ); #endif - -#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER +#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER ) + out.push_back( new glTFImporter() ); +#endif +#if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER ) out.push_back( new C4DImporter() ); #endif } diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 82c5c798a..668811e59 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -51,18 +51,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { - static const aiImporterDesc desc = { - "glTF Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour, - 0, - 0, - 0, - 0, - "gltf" - }; +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER + +static const aiImporterDesc desc = { + "glTF Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour, + 0, + 0, + 0, + 0, + "gltf" +}; glTFImporter::glTFImporter() : BaseImporter() @@ -95,6 +97,15 @@ void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IO // Allocate buffer and read file into it TextFileToBuffer( stream.get(), m_buffer ); + + std::string data( &m_buffer[ 0 ] ); + picojson::value v; + std::string err = picojson::parse( v, data ); + if (!err.empty()) { + throw DeadlyImportError( "Error occurred: " + err + "." ); + } } -} +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + +} // Namespace Assimp From b307ec643d37c964cbc423c713770465683c48e3 Mon Sep 17 00:00:00 2001 From: Otger Date: Fri, 27 Nov 2015 01:16:48 +0100 Subject: [PATCH 62/77] Created exporter class and fixed a few bugs --- code/CMakeLists.txt | 3 + code/Exporter.cpp | 9 + code/glTFExporter.cpp | 401 ++++++++++++++++++++++++++++++++++++++++++ code/glTFExporter.h | 87 +++++++++ code/glTFImporter.cpp | 39 ++-- code/glTFImporter.h | 18 -- code/glTFUtil.h | 18 ++ 7 files changed, 546 insertions(+), 29 deletions(-) create mode 100644 code/glTFExporter.cpp create mode 100644 code/glTFExporter.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 9a577fa1b..69ee3d7c7 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -568,6 +568,9 @@ ADD_ASSIMP_IMPORTER(GLTF glTFUtil.cpp glTFUtil.h glTFFileData.h + + glTFExporter.h + glTFExporter.cpp ) SET( Step_SRCS diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 42044b111..1d84e0dd0 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -87,6 +87,8 @@ void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportPro void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*); @@ -135,6 +137,13 @@ Exporter::ExportFormatEntry gExporters[] = aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices), #endif +#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER + Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF, + aiProcess_JoinIdenticalVertices), + Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, + aiProcess_JoinIdenticalVertices), +#endif + #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0), #endif diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp new file mode 100644 index 000000000..6e878165c --- /dev/null +++ b/code/glTFExporter.cpp @@ -0,0 +1,401 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + + +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER + +#include "glTFExporter.h" +#include "Exceptional.h" +#include "StringComparison.h" +#include "ByteSwapper.h" + +#include +#include +#include +#include +#include + +#include +#include + +#define RAPIDJSON_HAS_STDSTRING 1 +#include +#include +#include +#include + +#include "glTFFileData.h" +#include "glTFUtil.h" + +using namespace rapidjson; + +using namespace Assimp; +using namespace Assimp::glTF; + +namespace Assimp { + + // ------------------------------------------------------------------------------------------------ + // Worker function for exporting a scene to GLTF. Prototyped and registered in Exporter.cpp + void ExportSceneGLTF(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) + { + // invoke the exporter + glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, false); + } + + // ------------------------------------------------------------------------------------------------ + // Worker function for exporting a scene to GLB. Prototyped and registered in Exporter.cpp + void ExportSceneGLB(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) + { + // invoke the exporter + glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, true); + } + +} // end of namespace Assimp + + + +class glTFSceneExporter +{ + typedef std::gltf_unordered_map IdMap; + + Document& mDoc; + MemoryPoolAllocator<>& mAl; + + const aiScene* mScene; + + std::string mRootNodeId; + + std::vector mMeshIds; + + IdMap mUsedIds; + +public: + glTFSceneExporter(Document& doc, const aiScene* pScene) + : mDoc(doc) + , mAl(doc.GetAllocator()) + , mScene(pScene) + { + doc.SetObject(); + + for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) { + + } + + for (unsigned int i = 0; i < pScene->mNumCameras; ++i) { + + } + + for (unsigned int i = 0; i < pScene->mNumLights; ++i) { + + } + + for (unsigned int i = 0; i < pScene->mNumLights; ++i) { + + } + + for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { + + } + + + AddMeshes(); + + for (unsigned int i = 0; i < pScene->mNumTextures; ++i) { + + } + + AddNodes(); + + CreateScene(); + } + + inline void Pushf(Value& val, float f) + { + val.PushBack(Value(f).Move(), mAl); + } + + inline void SetMatrix(Value& v, const aiMatrix4x4& m) + { + v.SetArray(); + v.Reserve(16, mAl); + + Pushf(v, m.a1); Pushf(v, m.b1); Pushf(v, m.c1); Pushf(v, m.d1); + Pushf(v, m.a2); Pushf(v, m.b2); Pushf(v, m.c2); Pushf(v, m.d2); + Pushf(v, m.a3); Pushf(v, m.b3); Pushf(v, m.c3); Pushf(v, m.d3); + Pushf(v, m.a4); Pushf(v, m.b4); Pushf(v, m.c4); Pushf(v, m.d4); + } + + void AddMeshes() + { + if (mScene->mNumMeshes == 0) return; + + Value meshes; + meshes.SetObject(); + + mMeshIds.reserve(mScene->mNumMeshes); + for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) { + aiMesh* m = mScene->mMeshes[i]; + std::string meshId = FindID(m->mName, "mesh"); + mMeshIds.push_back(meshId); + + Value mesh; + mesh.SetObject(); + { + Value primitives; + primitives.SetObject(); + + + mesh.AddMember("primitives", primitives, mAl); + } + + meshes.AddMember(StringRef(mMeshIds.back()), mesh, mAl); + } + + mDoc.AddMember("meshes", meshes, mAl); + } + + void AddNodes() + { + if (!mScene->mRootNode) return; + + Value nodes; + nodes.SetObject(); + + mRootNodeId = AddNode(nodes, mScene->mRootNode); + + mDoc.AddMember("nodes", nodes, mAl); + } + + + std::string AddNode(Value& nodes, const aiNode* n) + { + std::string nodeId = FindID(n->mName, "node"); + + Value node; + node.SetObject(); + + if (!n->mTransformation.IsIdentity()) { + Value matrix; + SetMatrix(matrix, n->mTransformation); + node.AddMember("matrix", matrix, mAl); + } + + if (n->mNumMeshes > 0) { + Value meshes; + meshes.SetArray(); + for (unsigned int i = 0; i < n->mNumMeshes; ++i) { + meshes.PushBack(StringRef(mMeshIds[n->mMeshes[i]]), mAl); + } + node.AddMember("meshes", meshes, mAl); + } + + if (n->mNumChildren > 0) { + Value children; + children.SetArray(); + for (unsigned int i = 0; i < n->mNumChildren; ++i) { + std::string id = AddNode(nodes, n->mChildren[i]); + children.PushBack(Value(id, mAl), mAl); + } + node.AddMember("children", children, mAl); + } + + nodes.AddMember(Value(nodeId, mAl), node, mAl); + + return nodeId; + } + + void CreateScene() + { + const char* sceneName = "defaultScene"; + + mDoc.AddMember("scene", Value(sceneName, mAl), mAl); + + Value scenes; + scenes.SetObject(); + { + Value scene; + scene.SetObject(); + { + Value nodes; + nodes.SetArray(); + + if (!mRootNodeId.empty()) { + nodes.PushBack(StringRef(mRootNodeId), mAl); + } + + scene.AddMember("nodes", nodes, mAl); + } + scenes.AddMember(Value(sceneName, mAl), scene, mAl); + } + mDoc.AddMember("scenes", scenes, mAl); + } + + std::string FindID(const aiString& str, const char* suffix) + { + std::string id = str.C_Str(); + + IdMap::iterator it; + + if (!id.empty()) { + it = mUsedIds.find(id); + if (it == mUsedIds.end()) goto found; + + id += "-"; + } + + id += suffix; + + it = mUsedIds.find(id); + if (it == mUsedIds.end()) goto found; + + char buffer[256]; + int offset = sprintf(buffer, "%s-", id.c_str()); + for (int i = 0; ; ++i) { + ASSIMP_itoa10(buffer + offset, sizeof(buffer), i); + + id = buffer; + it = mUsedIds.find(id); + if (it == mUsedIds.end()) goto found; + } + + found: + mUsedIds[id] = true; + return id; + } +}; + + + +glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene, + const ExportProperties* pProperties, bool isBinary) + : mFilename(filename) + , mIOSystem(pIOSystem) + , mScene(pScene) + , mProperties(pProperties) + , mIsBinary(isBinary) +{ + boost::scoped_ptr outfile(pIOSystem->Open(mFilename, "wt")); + if (outfile == 0) { + throw DeadlyExportError("Could not open output file: " + std::string(mFilename)); + } + + if (isBinary) { + // we will write the header later, skip its size + outfile->Seek(sizeof(GLB_Header), aiOrigin_SET); + } + + + Document doc; + StringBuffer docBuffer; + { + glTFSceneExporter exportScene(doc, mScene); + + bool pretty = true; + if (!isBinary && pretty) { + PrettyWriter writer(docBuffer); + doc.Accept(writer); + } + else { + Writer writer(docBuffer); + doc.Accept(writer); + } + } + + if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { + throw DeadlyExportError("Failed to write scene data!"); + } + + if (isBinary) { + WriteBinaryData(outfile.get(), docBuffer.GetSize()); + } +} + + +void glTFExporter::WriteBinaryData(IOStream* outfile, std::size_t sceneLength) +{ + // + // write the body data + // + + if (!mBodyData.empty()) { + std::size_t bodyOffset = sizeof(GLB_Header) + sceneLength; + bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4 + + outfile->Seek(bodyOffset, aiOrigin_SET); + + if (outfile->Write(&mBodyData[0], mBodyData.size(), 1) != 1) { + throw DeadlyExportError("Failed to write body data!"); + } + } + + + // + // write the header + // + + outfile->Seek(0, aiOrigin_SET); + + GLB_Header header; + memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)); + + header.version = 1; + AI_SWAP4(header.version); + + header.length = sizeof(header) + sceneLength + mBodyData.size(); + AI_SWAP4(header.length); + + header.sceneLength = sceneLength; + AI_SWAP4(header.sceneLength); + + header.sceneFormat = SceneFormat_JSON; + AI_SWAP4(header.sceneFormat); + + if (outfile->Write(&header, sizeof(header), 1) != 1) { + throw DeadlyExportError("Failed to write the header!"); + } +} + + + + +#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/glTFExporter.h b/code/glTFExporter.h new file mode 100644 index 000000000..39dbf04d6 --- /dev/null +++ b/code/glTFExporter.h @@ -0,0 +1,87 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file GltfExporter.h +* Declares the exporter class to write a scene to a gltf/glb file +*/ +#ifndef AI_GLTFEXPORTER_H_INC +#define AI_GLTFEXPORTER_H_INC + +#include +#include +#include +#include + +struct aiScene; + +namespace Assimp +{ + class IOSystem; + class IOStream; + class ExportProperties; + + + // ------------------------------------------------------------------------------------------------ + /** Helper class to export a given scene to an glTF file. */ + // ------------------------------------------------------------------------------------------------ + class glTFExporter + { + public: + /// Constructor for a specific scene to export + glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene, + const ExportProperties* pProperties, bool binary); + + private: + + const char* mFilename; + IOSystem* mIOSystem; + const aiScene* mScene; + const ExportProperties* mProperties; + bool mIsBinary; + + std::vector mBodyData; + + void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); + + }; + +} + +#endif diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 374556af1..cc3b5dcf9 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "glTFFileData.h" #include "glTFUtil.h" +#define RAPIDJSON_HAS_STDSTRING 1 #include #include #include @@ -290,6 +291,10 @@ class glTFReader mScene->mRootNode = root; } } + + //if (!mScene->mRootNode) { + //mScene->mRootNode = new aiNode("EMPTY"); + //} } void SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType, @@ -550,13 +555,15 @@ struct Accessor template void ExtractData(T*& outData, unsigned int* outCount = 0, unsigned int* outComponents = 0) { - if (!data) return; + ai_assert(data); const std::size_t totalSize = elemSize * count; const std::size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); + ai_assert(count*byteStride <= bufferView->byteLength); + outData = new T[count]; if (byteStride == elemSize && targetElemSize == elemSize) { memcpy(outData, data, totalSize); @@ -574,6 +581,8 @@ struct Accessor template T GetValue(int i) { + ai_assert(data); + ai_assert(i*byteStride < bufferView->byteLength); T value = T(); memcpy(&value, data + i*byteStride, elemSize); //value >>= 8 * (sizeof(T) - elemSize); @@ -708,9 +717,11 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) else if (strcmp(attr, "NORMAL") == 0) { accessor->ExtractData(aimesh->mNormals); } - else if (strncmp(attr, "TEXCOORD_", 9) == 0) { + else if (strncmp(attr, "TEXCOORD_", 9) == 0) { int idx = attr[9] - '0'; - accessor->ExtractData(aimesh->mTextureCoords[idx], 0, &aimesh->mNumUVComponents[idx]); + if (idx >= 0 && idx <= AI_MAX_NUMBER_OF_TEXTURECOORDS) { + accessor->ExtractData(aimesh->mTextureCoords[idx], 0, &aimesh->mNumUVComponents[idx]); + } } } } @@ -727,7 +738,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) case PrimitiveMode_POINTS: { nFaces = acc->count; faces = new aiFace[nFaces]; - for (unsigned i = 0; i < acc->count; ++i) { + for (unsigned int i = 0; i < acc->count; ++i) { setFace(faces[i], acc->GetValue(i)); } break; @@ -736,7 +747,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) case PrimitiveMode_LINES: { nFaces = acc->count / 2; faces = new aiFace[nFaces]; - for (unsigned i = 0; i < acc->count; i += 2) { + for (unsigned int i = 0; i < acc->count; i += 2) { setFace(faces[i / 2], acc->GetValue(i), acc->GetValue(i + 1)); } break; @@ -747,7 +758,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) nFaces = acc->count - ((primitiveMode == PrimitiveMode_LINE_STRIP) ? 1 : 0); faces = new aiFace[nFaces]; setFace(faces[0], acc->GetValue(0), acc->GetValue(1)); - for (unsigned i = 2; i < acc->count; ++i) { + for (unsigned int i = 2; i < acc->count; ++i) { setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetValue(i)); } if (primitiveMode == PrimitiveMode_LINE_LOOP) { // close the loop @@ -759,7 +770,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) case PrimitiveMode_TRIANGLES: { nFaces = acc->count / 3; faces = new aiFace[nFaces]; - for (unsigned i = 0; i < acc->count; i += 3) { + for (unsigned int i = 0; i < acc->count; i += 3) { setFace(faces[i / 3], acc->GetValue(i), acc->GetValue(i + 1), acc->GetValue(i + 2)); } break; @@ -768,7 +779,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) nFaces = acc->count - 2; faces = new aiFace[nFaces]; setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2)); - for (unsigned i = 3; i < acc->count; ++i) { + for (unsigned int i = 3; i < acc->count; ++i) { setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetValue(i)); } break; @@ -777,7 +788,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) nFaces = acc->count - 2; faces = new aiFace[nFaces]; setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2)); - for (unsigned i = 3; i < acc->count; ++i) { + for (unsigned int i = 3; i < acc->count; ++i) { setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetValue(i)); } break; @@ -986,8 +997,10 @@ aiNode* glTFReader::LoadNode(const char* id, Value& node) if (child.IsString()) { // get/create the child node aiNode* aichild = mNodes.Get(child.GetString()); - aichild->mParent = ainode; - ainode->mChildren[ainode->mNumChildren++] = aichild; + if (aichild) { + aichild->mParent = ainode; + ainode->mChildren[ainode->mNumChildren++] = aichild; + } } } } @@ -1185,4 +1198,8 @@ void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IO // import the data glTFReader reader(pScene, doc, *pIOHandler, bodyBuffer); reader.Load(); + + if (pScene->mNumMeshes == 0) { + pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; + } } diff --git a/code/glTFImporter.h b/code/glTFImporter.h index 9254040c1..3de899915 100644 --- a/code/glTFImporter.h +++ b/code/glTFImporter.h @@ -44,24 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "LogAux.h" #include "DefaultIOSystem.h" -#if _MSC_VER > 1500 || (defined __GNUC___) -# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP -# else -# define gltf_unordered_map map -# define gltf_unordered_multimap multimap -#endif - -#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP -# include -# if _MSC_VER > 1600 -# define gltf_unordered_map unordered_map -# define gltf_unordered_multimap unordered_multimap -# else -# define gltf_unordered_map tr1::unordered_map -# define gltf_unordered_multimap tr1::unordered_multimap -# endif -#endif - namespace Assimp { /** diff --git a/code/glTFUtil.h b/code/glTFUtil.h index 010d50ee3..089632ca1 100644 --- a/code/glTFUtil.h +++ b/code/glTFUtil.h @@ -44,6 +44,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //#include "MemoryIOWrapper.h" #include "StringComparison.h" +#if _MSC_VER > 1500 || (defined __GNUC___) +# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP +# else +# define gltf_unordered_map map +# define gltf_unordered_multimap multimap +#endif + +#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP +# include +# if _MSC_VER > 1600 +# define gltf_unordered_map unordered_map +# define gltf_unordered_multimap unordered_multimap +# else +# define gltf_unordered_map tr1::unordered_map +# define gltf_unordered_multimap tr1::unordered_multimap +# endif +#endif + namespace Assimp { namespace glTF { From 5942d60aeaf5dff4c1b1130285161166d2965c81 Mon Sep 17 00:00:00 2001 From: Otger Date: Fri, 27 Nov 2015 02:31:18 +0100 Subject: [PATCH 63/77] Fixed gcc errors --- code/glTFExporter.cpp | 46 ++++++++++----------- code/glTFImporter.cpp | 96 ++++++++++++++++++++++--------------------- 2 files changed, 73 insertions(+), 69 deletions(-) diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 6e878165c..eb133cccb 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -233,12 +233,12 @@ public: children.SetArray(); for (unsigned int i = 0; i < n->mNumChildren; ++i) { std::string id = AddNode(nodes, n->mChildren[i]); - children.PushBack(Value(id, mAl), mAl); + children.PushBack(Value(id, mAl).Move(), mAl); } node.AddMember("children", children, mAl); } - nodes.AddMember(Value(nodeId, mAl), node, mAl); + nodes.AddMember(Value(nodeId, mAl).Move(), node, mAl); return nodeId; } @@ -247,7 +247,7 @@ public: { const char* sceneName = "defaultScene"; - mDoc.AddMember("scene", Value(sceneName, mAl), mAl); + mDoc.AddMember("scene", Value(sceneName, mAl).Move(), mAl); Value scenes; scenes.SetObject(); @@ -264,7 +264,7 @@ public: scene.AddMember("nodes", nodes, mAl); } - scenes.AddMember(Value(sceneName, mAl), scene, mAl); + scenes.AddMember(Value(sceneName, mAl).Move(), scene, mAl); } mDoc.AddMember("scenes", scenes, mAl); } @@ -275,29 +275,29 @@ public: IdMap::iterator it; - if (!id.empty()) { + do { + if (!id.empty()) { + it = mUsedIds.find(id); + if (it == mUsedIds.end()) break; + + id += "-"; + } + + id += suffix; + it = mUsedIds.find(id); - if (it == mUsedIds.end()) goto found; + if (it == mUsedIds.end()) break; - id += "-"; - } + char buffer[256]; + int offset = sprintf(buffer, "%s-", id.c_str()); + for (int i = 0; it == mUsedIds.end(); ++i) { + ASSIMP_itoa10(buffer + offset, sizeof(buffer), i); - id += suffix; + id = buffer; + it = mUsedIds.find(id); + } + } while (false); // fake loop to allow using "break" - it = mUsedIds.find(id); - if (it == mUsedIds.end()) goto found; - - char buffer[256]; - int offset = sprintf(buffer, "%s-", id.c_str()); - for (int i = 0; ; ++i) { - ASSIMP_itoa10(buffer + offset, sizeof(buffer), i); - - id = buffer; - it = mUsedIds.find(id); - if (it == mUsedIds.end()) goto found; - } - - found: mUsedIds[id] = true; return id; } diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 719c53b75..2df1ea458 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -79,10 +79,8 @@ typedef rapidjson::Value::MemberIterator MemIt; // JSON Value reading helpers // -inline static void Getf(const Value& v, float& out) -{ - if (v.IsNumber()) out = static_cast(v.GetDouble()); -} + +#define GETF(VAL, OUT) { if ((VAL).IsNumber()) (OUT) = static_cast((VAL).GetDouble()); } template struct ReadHelper { }; @@ -109,28 +107,28 @@ template<> struct ReadHelper { static bool Read(Value& val, std::st template<> struct ReadHelper { static bool Read(Value& v, aiColor3D& out) { if (!v.IsArray() || v.Size() < 3) return false; - Getf(v[0], out.r); Getf(v[1], out.g); Getf(v[2], out.b); + GETF(v[0], out.r); GETF(v[1], out.g); GETF(v[2], out.b); return true; }}; template<> struct ReadHelper { static bool Read(Value& v, aiVector3D& out) { if (!v.IsArray() || v.Size() != 3) return false; - Getf(v[0], out.x); Getf(v[1], out.y); Getf(v[2], out.z); + GETF(v[0], out.x); GETF(v[1], out.y); GETF(v[2], out.z); return true; }}; template<> struct ReadHelper { static bool Read(Value& v, aiQuaternion& out) { if (!v.IsArray() || v.Size() != 4) return false; - Getf(v[0], out.x); Getf(v[1], out.y); Getf(v[2], out.z); Getf(v[3], out.w); + GETF(v[0], out.x); GETF(v[1], out.y); GETF(v[2], out.z); GETF(v[3], out.w); return true; }}; template<> struct ReadHelper { static bool Read(Value& v, aiMatrix4x4& o) { if (!v.IsArray() || v.Size() != 16) return false; - Getf(v[ 0], o.a1); Getf(v[ 1], o.b1); Getf(v[ 2], o.c1); Getf(v[ 3], o.d1); - Getf(v[ 4], o.a2); Getf(v[ 5], o.b2); Getf(v[ 6], o.c2); Getf(v[ 7], o.d2); - Getf(v[ 8], o.a3); Getf(v[ 9], o.b3); Getf(v[10], o.c3); Getf(v[11], o.d3); - Getf(v[12], o.a4); Getf(v[13], o.b4); Getf(v[14], o.c4); Getf(v[15], o.d4); + GETF(v[ 0], o.a1); GETF(v[ 1], o.b1); GETF(v[ 2], o.c1); GETF(v[ 3], o.d1); + GETF(v[ 4], o.a2); GETF(v[ 5], o.b2); GETF(v[ 6], o.c2); GETF(v[ 7], o.d2); + GETF(v[ 8], o.a3); GETF(v[ 9], o.b3); GETF(v[10], o.c3); GETF(v[11], o.d3); + GETF(v[12], o.a4); GETF(v[13], o.b4); GETF(v[14], o.c4); GETF(v[15], o.d4); return true; }}; @@ -167,34 +165,32 @@ typedef std::pair Range; // glTFReader class // -class glTFReader; - //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID -template +template< class T, class INST, T(INST::*FACTORY_FN)(const char*, Value&)> class LazyDict { typedef typename std::gltf_unordered_map Map; Value* mDict; //! JSON dictionary object const char* mDictId; //! ID of the dictionary object - glTFReader& mInstance; //! The glTFReader instance + INST& mInstance; //! The reader object instance Map mReadObjs; //! The read objects public: - LazyDict(glTFReader& instance, const char* dictId) + LazyDict(INST& instance, const char* dictId) : mDictId(dictId), mInstance(instance) { Document& doc = mInstance.GetDocument(); MemIt it = doc.FindMember(dictId); - mDict = (it != doc.MemberEnd() && it->value.IsObject()) ? &it->value : nullptr; + mDict = (it != doc.MemberEnd() && it->value.IsObject()) ? &it->value : 0; } T Get(const char* id) { if (!mDict) return T(); // section was missing - Map::iterator it = mReadObjs.find(id); + typename Map::iterator it = mReadObjs.find(id); if (it != mReadObjs.end()) { // already created? return it->second; } @@ -249,22 +245,22 @@ class glTFReader typedef glTFReader T; // (to shorten next declarations) - LazyDict, &T::LoadAccessor> mAccessors; - //LazyDict mAnimations; - //LazyDict mAssets; - LazyDict, &T::LoadBuffer> mBuffers; - LazyDict, &T::LoadBufferView> mBufferViews; - //LazyDict mCameras; - LazyDict, &T::LoadImage> mImages; - LazyDict mMaterials; - LazyDict mMeshes; - LazyDict mNodes; - //LazyDict, &T::LoadProgram> mPrograms; - //LazyDict, &T::LoadSampler> mSamplers; - //LazyDict, &T::LoadShader> mShaders; - //LazyDict, &T::LoadSkin> mSkins; - //LazyDict,&T::LoadTechnique> mTechniques; - LazyDict, &T::LoadTexture> mTextures; + LazyDict, T, &T::LoadAccessor> mAccessors; + //LazyDict mAnimations; + //LazyDict mAssets; + LazyDict, T, &T::LoadBuffer> mBuffers; + LazyDict, T, &T::LoadBufferView> mBufferViews; + //LazyDict mCameras; + LazyDict, T, &T::LoadImage> mImages; + LazyDict mMaterials; + LazyDict mMeshes; + LazyDict mNodes; + //LazyDict, T, &T::LoadProgram> mPrograms; + //LazyDict, T, &T::LoadSampler> mSamplers; + //LazyDict, T, &T::LoadShader> mShaders; + //LazyDict, T, &T::LoadSkin> mSkins; + //LazyDict,T, &T::LoadTechnique> mTechniques; + LazyDict, T, &T::LoadTexture> mTextures; void LoadScene(Value& scene) @@ -477,7 +473,8 @@ Ptr glTFReader::LoadBuffer(const char* id, Value& obj) if (isBase64) { uint8_t* data; std::size_t dataLen = DecodeBase64(comma + 1, data); - b = new Buffer(shared_ptr(data), dataLen); + shared_ptr dataptr(data); + b = new Buffer(dataptr, dataLen); } } else if (uri) { // Local file @@ -581,7 +578,8 @@ struct Accessor if (outComponents) *outComponents = numComponents; } - template + //! Gets the i-th value as defined by the accessor + template T GetValue(int i) { ai_assert(data); @@ -590,7 +588,13 @@ struct Accessor memcpy(&value, data + i*byteStride, elemSize); //value >>= 8 * (sizeof(T) - elemSize); return value; - } + } + + //! Gets the i-th value as defined by the accessor + unsigned int GetUInt(int i) + { + return GetValue(i); + } }; Ptr glTFReader::LoadAccessor(const char* id, Value& obj) @@ -742,7 +746,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) nFaces = acc->count; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < acc->count; ++i) { - setFace(faces[i], acc->GetValue(i)); + setFace(faces[i], acc->GetUInt(i)); } break; } @@ -751,7 +755,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) nFaces = acc->count / 2; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < acc->count; i += 2) { - setFace(faces[i / 2], acc->GetValue(i), acc->GetValue(i + 1)); + setFace(faces[i / 2], acc->GetUInt(i), acc->GetUInt(i + 1)); } break; } @@ -760,9 +764,9 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) case PrimitiveMode_LINE_STRIP: { nFaces = acc->count - ((primitiveMode == PrimitiveMode_LINE_STRIP) ? 1 : 0); faces = new aiFace[nFaces]; - setFace(faces[0], acc->GetValue(0), acc->GetValue(1)); + setFace(faces[0], acc->GetUInt(0), acc->GetUInt(1)); for (unsigned int i = 2; i < acc->count; ++i) { - setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetValue(i)); + setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetUInt(i)); } if (primitiveMode == PrimitiveMode_LINE_LOOP) { // close the loop setFace(faces[acc->count - 1], faces[acc->count - 2].mIndices[1], faces[0].mIndices[0]); @@ -774,25 +778,25 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh) nFaces = acc->count / 3; faces = new aiFace[nFaces]; for (unsigned int i = 0; i < acc->count; i += 3) { - setFace(faces[i / 3], acc->GetValue(i), acc->GetValue(i + 1), acc->GetValue(i + 2)); + setFace(faces[i / 3], acc->GetUInt(i), acc->GetUInt(i + 1), acc->GetUInt(i + 2)); } break; } case PrimitiveMode_TRIANGLE_STRIP: { nFaces = acc->count - 2; faces = new aiFace[nFaces]; - setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2)); + setFace(faces[0], acc->GetUInt(0), acc->GetUInt(1), acc->GetUInt(2)); for (unsigned int i = 3; i < acc->count; ++i) { - setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetValue(i)); + setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetUInt(i)); } break; } case PrimitiveMode_TRIANGLE_FAN: nFaces = acc->count - 2; faces = new aiFace[nFaces]; - setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2)); + setFace(faces[0], acc->GetUInt(0), acc->GetUInt(1), acc->GetUInt(2)); for (unsigned int i = 3; i < acc->count; ++i) { - setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetValue(i)); + setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetUInt(i)); } break; } From ba35c97e9d9fcfdca40f7fc43cf185e0556e95bb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 28 Nov 2015 10:06:26 +0100 Subject: [PATCH 64/77] assimp/assimp/issues/698: Increase upper limits for hints. --- code/Importer.cpp | 2 +- include/assimp/Importer.hpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/code/Importer.cpp b/code/Importer.cpp index c30ffc2cf..aa0b51a93 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -491,7 +491,7 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, pHint = ""; } - if (!pBuffer || !pLength || strlen(pHint) > 100) { + if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) { pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()"; return NULL; } diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 917c980d0..73c95f0e1 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -114,6 +114,9 @@ namespace Assimp { * threads for loading, each thread should maintain its own Importer instance. */ class ASSIMP_API Importer { +public: + /// @brief The upper limit for hints. + static const unsigned int MaxLenHint = 200; public: From 91a6ff7f0e2e54d0aa0844c3d9f21d9ce2203b87 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 28 Nov 2015 12:05:55 +0100 Subject: [PATCH 65/77] Importer: fix doxygen comment style to default. --- include/assimp/Importer.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 73c95f0e1..b8b471469 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -115,7 +115,9 @@ namespace Assimp { */ class ASSIMP_API Importer { public: - /// @brief The upper limit for hints. + /** + * @brief The upper limit for hints. + */ static const unsigned int MaxLenHint = 200; public: From 4f757cdf5a904feb65b39168cad9b2ff9ac18e5f Mon Sep 17 00:00:00 2001 From: Otger Date: Sun, 29 Nov 2015 19:13:51 +0100 Subject: [PATCH 66/77] Implemented basic glTF exporter and improved the importer (plus some code refactor) --- code/BaseImporter.h | 21 + code/CMakeLists.txt | 10 +- code/Exporter.cpp | 4 +- code/glTFAsset.h | 933 ++++++++++++++ code/glTFAsset.inl | 1212 ++++++++++++++++++ code/{glTFUtil.h => glTFAssetWriter.h} | 64 +- code/glTFAssetWriter.inl | 490 +++++++ code/glTFExporter.cpp | 528 ++++---- code/glTFExporter.h | 25 +- code/glTFFileData.h | 122 -- code/glTFImporter.cpp | 1616 ++++++++---------------- code/glTFImporter.h | 27 +- code/glTFUtil.cpp | 164 --- 13 files changed, 3501 insertions(+), 1715 deletions(-) create mode 100644 code/glTFAsset.h create mode 100644 code/glTFAsset.inl rename code/{glTFUtil.h => glTFAssetWriter.h} (62%) create mode 100644 code/glTFAssetWriter.inl delete mode 100644 code/glTFFileData.h delete mode 100644 code/glTFUtil.cpp diff --git a/code/BaseImporter.h b/code/BaseImporter.h index cb6394ebc..7c34ac5fe 100644 --- a/code/BaseImporter.h +++ b/code/BaseImporter.h @@ -359,6 +359,27 @@ public: // static utilities IOStream* stream, std::vector& data); + // ------------------------------------------------------------------- + /** Utility function to move a std::vector into a aiScene array + * @param vec The vector to be moved + * @param out The output pointer to the allocated array. + * @param numOut The output count of elements copied. */ + template + AI_FORCE_INLINE + static void CopyVector( + std::vector& vec, + T*& out, + unsigned int& outLength) + { + outLength = vec.size(); + if (outLength) { + out = new T[outLength]; + std::swap_ranges(vec.begin(), vec.end(), out); + } + } + + + protected: /** Error description in case there was one. */ diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 69ee3d7c7..dffb3b474 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -563,12 +563,14 @@ ADD_ASSIMP_IMPORTER(X ) ADD_ASSIMP_IMPORTER(GLTF + glTFAsset.h + glTFAsset.inl + glTFAssetWriter.h + glTFAssetWriter.inl + glTFImporter.cpp glTFImporter.h - glTFUtil.cpp - glTFUtil.h - glTFFileData.h - + glTFExporter.h glTFExporter.cpp ) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 1d84e0dd0..215fa671c 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -139,9 +139,9 @@ Exporter::ExportFormatEntry gExporters[] = #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF, - aiProcess_JoinIdenticalVertices), + aiProcess_JoinIdenticalVertices | aiProcess_SortByPType), Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, - aiProcess_JoinIdenticalVertices), + aiProcess_JoinIdenticalVertices | aiProcess_SortByPType), #endif #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER diff --git a/code/glTFAsset.h b/code/glTFAsset.h new file mode 100644 index 000000000..4f6c37a3f --- /dev/null +++ b/code/glTFAsset.h @@ -0,0 +1,933 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file glTFAsset.h + * Declares a glTF class to handle gltf/glb files + * + * glTF Extensions Support: + * KHR_binary_glTF: full + * KHR_materials_common: full + */ +#ifndef glTFAsset_H_INC +#define glTFAsset_H_INC + +#include +#include +#include +#include +#include + +#define RAPIDJSON_HAS_STDSTRING 1 +#include +#include +#include + +#ifdef ASSIMP_API +# include "boost/shared_ptr.hpp" +# include "DefaultIOSystem.h" +# include "ByteSwapper.h" +#else +# include +# define AI_SWAP4(p) +# define ai_assert +#endif + + +#if _MSC_VER > 1500 || (defined __GNUC___) +# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP +# else +# define gltf_unordered_map map +#endif + +#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP +# include +# if _MSC_VER > 1600 +# define gltf_unordered_map unordered_map +# else +# define gltf_unordered_map tr1::unordered_map +# endif +#endif + +namespace glTF +{ +#ifdef ASSIMP_API + using Assimp::IOStream; + using Assimp::IOSystem; + using boost::shared_ptr; +#else + using std::shared_ptr; + + typedef std::runtime_error DeadlyImportError; + typedef std::runtime_error DeadlyExportError; + + enum aiOrigin { aiOrigin_SET = 0, aiOrigin_CUR = 1, aiOrigin_END = 2 }; + class IOSystem; + class IOStream + { + FILE* f; + public: + IOStream(FILE* file) : f(file) {} + ~IOStream() { fclose(f); f = 0; } + + size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); } + size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); } + int Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); } + size_t Tell() const { return ftell(f); } + + size_t FileSize() { + long p = Tell(), len = (Seek(0, aiOrigin_END), Tell()); + return size_t((Seek(p, aiOrigin_SET), len)); + } + }; +#endif + + using rapidjson::Value; + using rapidjson::Document; + + class Asset; + class AssetWriter; + + struct BufferView; // here due to cross-reference + struct Texture; + struct Light; + + + // Vec/matrix types, as raw float arrays + typedef float (vec3)[3]; + typedef float (vec4)[4]; + typedef float (mat4)[16]; + + + namespace Util + { + void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out); + + size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out); + + inline size_t DecodeBase64(const char* in, uint8_t*& out) + { + return DecodeBase64(in, strlen(in), out); + } + + struct DataURI + { + const char* mediaType; + const char* charset; + bool base64; + const char* data; + size_t dataLength; + }; + + //! Check if a uri is a data URI + inline bool ParseDataURI(const char* uri, size_t uriLen, DataURI& out); + } + + + //! Magic number for GLB files + #define AI_GLB_MAGIC_NUMBER "glTF" + + #ifdef ASSIMP_API + #include "./../include/assimp/Compiler/pushpack1.h" + #endif + + //! For the KHR_binary_glTF extension (binary .glb file) + //! 20-byte header (+ the JSON + a "body" data section) + struct GLB_Header + { + uint8_t magic[4]; //!< Magic number: "glTF" + uint32_t version; //!< Version number (always 1 as of the last update) + uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes + uint32_t sceneLength; //!< Length, in bytes, of the glTF scene + uint32_t sceneFormat; //!< Specifies the format of the glTF scene (see the SceneFormat enum) + } PACK_STRUCT; + + #ifdef ASSIMP_API + #include "./../include/assimp/Compiler/poppack1.h" + #endif + + + //! Values for the GLB_Header::sceneFormat field + enum SceneFormat + { + SceneFormat_JSON = 0 + }; + + //! Values for the mesh primitive modes + enum PrimitiveMode + { + PrimitiveMode_POINTS = 0, + PrimitiveMode_LINES = 1, + PrimitiveMode_LINE_LOOP = 2, + PrimitiveMode_LINE_STRIP = 3, + PrimitiveMode_TRIANGLES = 4, + PrimitiveMode_TRIANGLE_STRIP = 5, + PrimitiveMode_TRIANGLE_FAN = 6 + }; + + //! Values for the Accessor::componentType field + enum ComponentType + { + ComponentType_BYTE = 5120, + ComponentType_UNSIGNED_BYTE = 5121, + ComponentType_SHORT = 5122, + ComponentType_UNSIGNED_SHORT = 5123, + ComponentType_FLOAT = 5126 + }; + + inline size_t ComponentTypeSize(ComponentType t) + { + switch (t) { + case ComponentType_SHORT: + case ComponentType_UNSIGNED_SHORT: + return 2; + + case ComponentType_FLOAT: + return 4; + + //case Accessor::ComponentType_BYTE: + //case Accessor::ComponentType_UNSIGNED_BYTE: + default: + return 1; + } + } + + //! Values for the BufferView::target field + enum BufferViewTarget + { + BufferViewTarget_ARRAY_BUFFER = 34962, + BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963 + }; + + //! Values for the Texture::format and Texture::internalFormat fields + enum TextureFormat + { + TextureFormat_ALPHA = 6406, + TextureFormat_RGB = 6407, + TextureFormat_RGBA = 6408, + TextureFormat_LUMINANCE = 6409, + TextureFormat_LUMINANCE_ALPHA = 6410 + }; + + //! Values for the Texture::target field + enum TextureTarget + { + TextureTarget_TEXTURE_2D = 3553 + }; + + //! Values for the Texture::type field + enum TextureType + { + TextureType_UNSIGNED_BYTE = 5121, + TextureType_UNSIGNED_SHORT_5_6_5 = 33635, + TextureType_UNSIGNED_SHORT_4_4_4_4 = 32819, + TextureType_UNSIGNED_SHORT_5_5_5_1 = 32820 + }; + + + //! Values for the Accessor::type field (helper class) + class AttribType + { + public: + enum Value + { SCALAR, VEC2, VEC3, VEC4, MAT2, MAT3, MAT4 }; + + private: + static const size_t NUM_VALUES = static_cast(MAT4)+1; + + struct Info + { const char* name; unsigned int numComponents; }; + + template struct data + { static const Info infos[NUM_VALUES]; }; + + public: + inline static Value FromString(const char* str) + { + for (size_t i = 0; i < NUM_VALUES; ++i) { + if (strcmp(data<0>::infos[i].name, str) == 0) { + return static_cast(i); + } + } + return SCALAR; + } + + inline static const char* ToString(Value type) + { + return data<0>::infos[static_cast(type)].name; + } + + inline static unsigned int GetNumComponents(Value type) + { + return data<0>::infos[static_cast(type)].numComponents; + } + }; + + // must match the order of the AttribTypeTraits::Value enum! + template const AttribType::Info + AttribType::data::infos[AttribType::NUM_VALUES] = { + { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 } + }; + + + + //! A reference to one top-level object, which is valid + //! until the Asset instance is destroyed + template + class Ref + { + std::vector* vector; + int index; + + public: + Ref() : vector(0), index(0) {} + Ref(std::vector& vec, int idx) : vector(&vec), index(idx) {} + + inline size_t GetIndex() const + { return index; } + + operator bool() const + { return vector != 0; } + + T* operator->() + { return (*vector)[index]; } + + T& operator*() + { return *((*vector)[index]); } + }; + + //! Helper struct to represent values that might not be present + template + struct Nullable + { + T value; + bool isPresent; + + Nullable() : isPresent(false) {} + Nullable(T& val) : value(val), isPresent(true) {} + }; + + + //! Base classe for all glTF top-level objects + struct Object + { + std::string id; //!< The globally unique ID used to reference this object + std::string name; //!< The user-defined name of this object + + //! Objects marked as special are not exported (used to emulate the binary body buffer) + virtual bool IsSpecial() const + { return false; } + }; + + + + // + // Classes for each glTF top-level object type + // + + //! A typed view into a BufferView. A BufferView contains raw binary data. + //! An accessor provides a typed view into a BufferView or a subset of a BufferView + // !similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. + struct Accessor : public Object + { + Ref bufferView; //!< The ID of the bufferView. (required) + unsigned int byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) + unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0) + ComponentType componentType; //!< The datatype of components in the attribute. (required) + unsigned int count; //!< The number of attributes referenced by this accessor. (required) + AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) + //std::vector max; //!< Maximum value of each component in this attribute. + //std::vector min; //!< Minimum value of each component in this attribute. + + unsigned int GetNumComponents(); + unsigned int GetBytesPerComponent(); + unsigned int GetElementSize(); + + inline uint8_t* GetPointer(); + + template + void ExtractData(T*& outData); + + void WriteData(size_t count, const void* src_buffer, size_t src_stride); + + //! Helper class to iterate the data + class Indexer + { + friend struct Accessor; + + uint8_t* data; + Accessor& accessor; + size_t elemSize, stride; + + Indexer(Accessor& acc); + + public: + + //! Accesses the i-th value as defined by the accessor + template + T GetValue(int i); + + //! Accesses the i-th value as defined by the accessor + inline unsigned int GetUInt(int i) + { + return GetValue(i); + } + }; + + inline Indexer GetIndexer() + { + return Indexer(*this); + } + + Accessor() {} + void Read(Value& obj, Asset& r); + }; + + + struct Animation : public Object + { + struct Channel + { + + }; + + struct Target + { + + }; + + struct Sampler + { + + }; + }; + + //! A buffer points to binary geometry, animation, or skins. + struct Buffer : public Object + { + public: + + enum Type + { + Type_arraybuffer, + Type_text + }; + + //std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required) + size_t byteLength; //!< The length of the buffer in bytes. (default: 0) + //std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer") + + Type type; + + private: + shared_ptr mData; //!< Pointer to the data + bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer) + + public: + Buffer(); + + void Read(Value& obj, Asset& r); + + void LoadFromStream(IOStream& stream, size_t length = 0, size_t baseOffset = 0); + + size_t AppendData(uint8_t* data, size_t length); + void Grow(size_t amount); + + uint8_t* GetPointer() + { return mData.get(); } + + void MarkAsSpecial() + { mIsSpecial = true; } + + bool IsSpecial() const + { return mIsSpecial; } + }; + + + //! A view into a buffer generally representing a subset of the buffer. + struct BufferView : public Object + { + Ref buffer; //! The ID of the buffer. (required) + size_t byteOffset; //! The offset into the buffer in bytes. (required) + size_t byteLength; //! The length of the bufferView in bytes. (default: 0) + + BufferViewTarget target; //! The target that the WebGL buffer should be bound to. + + BufferView() {} + void Read(Value& obj, Asset& r); + }; + + + struct Camera : public Object + { + enum Type + { + Perspective, + Orthographic + }; + + Type type; + + union + { + struct { + float aspectRatio; //! bufferView; + + std::string mimeType; + + private: + uint8_t* mData; + size_t mDataLength; + + public: + + Image(); + void Read(Value& obj, Asset& r); + + inline bool HasData() const + { return mDataLength > 0; } + + inline size_t GetDataLength() const + { return mDataLength; } + + inline const uint8_t* GetData() const + { return mData; } + + inline uint8_t* StealData(); + + inline void SetData(uint8_t* data, size_t length, Asset& r); + }; + + //! Holds a material property that can be a texture or a color + struct TexProperty + { + Ref texture; + vec4 color; + }; + + //! The material appearance of a primitive. + struct Material : public Object + { + //Ref source; //!< The ID of the technique. + //std::gltf_unordered_map values; //!< A dictionary object of parameter values. + + //! Techniques defined by KHR_materials_common + enum Technique + { + Technique_undefined = 0, + Technique_BLINN, + Technique_PHONG, + Technique_LAMBERT, + Technique_CONSTANT + }; + + TexProperty ambient; + TexProperty diffuse; + TexProperty specular; + TexProperty emission; + + bool doubleSided; + bool transparent; + float transparency; + float shininess; + + Technique technique; + + Material() { SetDefaults(); } + void Read(Value& obj, Asset& r); + void SetDefaults(); + }; + + //! A set of primitives to be rendered. A node can contain one or more meshes. A node's transform places the mesh in the scene. + struct Mesh : public Object + { + typedef std::vector< Ref > AccessorList; + + struct Primitive + { + PrimitiveMode mode; + + struct Attributes { + AccessorList position, normal, texcoord, color, joint, jointmatrix, weight; + } attributes; + + Ref indices; + + Ref material; + }; + + std::vector primitives; + + Mesh() {} + void Read(Value& obj, Asset& r); + }; + + struct Node : public Object + { + std::vector< Ref > children; + std::vector< Ref > meshes; + + Nullable matrix; + Nullable translation; + Nullable rotation; + Nullable scale; + + Ref camera; + Ref light; + + Node() {} + void Read(Value& obj, Asset& r); + }; + + struct Program : public Object + { + Program() {} + void Read(Value& obj, Asset& r); + }; + + + struct Sampler : public Object + { + Sampler() {} + void Read(Value& obj, Asset& r); + }; + + struct Scene : public Object + { + std::vector< Ref > nodes; + + Scene() {} + void Read(Value& obj, Asset& r); + }; + + struct Shader : public Object + { + Shader() {} + void Read(Value& obj, Asset& r); + }; + + struct Skin : public Object + { + Skin() {} + void Read(Value& obj, Asset& r); + }; + + struct Technique : public Object + { + struct Parameters + { + + }; + + struct States + { + + }; + + struct Functions + { + + }; + + Technique() {} + void Read(Value& obj, Asset& r); + }; + + //! A texture and its sampler. + struct Texture : public Object + { + //Ref source; //!< The ID of the sampler used by this texture. (required) + Ref source; //!< The ID of the image used by this texture. (required) + + //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA) + //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA) + + //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D) + //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE) + + Texture() {} + void Read(Value& obj, Asset& r); + }; + + + //! A light (from KHR_materials_common extension) + struct Light : public Object + { + enum Type + { + Type_undefined, + Type_ambient, + Type_directional, + Type_point, + Type_spot + }; + + Type type; + + vec4 color; + float distance; + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; + float falloffAngle; + float falloffExponent; + + Light() {} + void Read(Value& obj, Asset& r); + + void SetDefaults(); + }; + + //! Base class for LazyDict that acts as an interface + class LazyDictBase + { + public: + virtual ~LazyDictBase() {} + + virtual void AttachToDocument(Document& doc) = 0; + virtual void DetachFromDocument() = 0; + + virtual void WriteObjects(AssetWriter& writer) = 0; + }; + + //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID + //! It is the owner the loaded objects, so when it is destroyed it also deletes them + template + class LazyDict : public LazyDictBase + { + friend class Asset; + friend class AssetWriter; + + typedef typename std::gltf_unordered_map< std::string, size_t > Dict; + + std::vector mObjs; //! The read objects + Dict mObjsById; //! The read objects accesible by id + const char* mDictId; //! ID of the dictionary object + const char* mExtId; //! ID of the extension defining the dictionary + Value* mDict; //! JSON dictionary object + Asset& mAsset; //! The asset instance + + void AttachToDocument(Document& doc); + void DetachFromDocument(); + + void WriteObjects(AssetWriter& writer); + + Ref Add(T* obj); + + public: + LazyDict(Asset& asset, const char* dictId, const char* extId = 0); + ~LazyDict(); + + Ref Get(const char* id); + Ref Get(size_t i); + + Ref Create(const char* id); + Ref Create(const std::string& id) + { return Create(id.c_str()); } + + inline size_t Size() const + { return mObjs.size(); } + + inline T& operator[](size_t i) + { return *mObjs[i]; } + + }; + + + struct AssetMetadata + { + std::string copyright; //!< A copyright message suitable for display to credit the content creator. + std::string generator; //!< Tool that generated this glTF model.Useful for debugging. + bool premultipliedAlpha; //!< Specifies if the shaders were generated with premultiplied alpha. (default: false) + + struct { + std::string api; //!< Specifies the target rendering API (default: "WebGL") + std::string version; //!< Specifies the target rendering API (default: "1.0.3") + } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {}) + + int version; //!< The glTF format version (should be 1) + + void Read(Document& doc); + }; + + // + // glTF Asset class + // + + //! Root object for a glTF asset + class Asset + { + typedef std::gltf_unordered_map IdMap; + + template + friend class LazyDict; + + friend struct Buffer; // To access OpenFile + + friend class AssetWriter; + + private: + IOSystem* mIOSystem; + + std::string mCurrentAssetDir; + + size_t mSceneLength; + size_t mBodyOffset, mBodyLength; + + std::vector mDicts; + + IdMap mUsedIds; + + Ref mBodyBuffer; + + Asset(Asset&); + Asset& operator=(const Asset&); + + public: + + //! Keeps info about the enabled extensions + struct Extensions + { + bool KHR_binary_glTF; + bool KHR_materials_common; + + } extensionsUsed; + + AssetMetadata asset; + + + // Dictionaries for each type of object + + LazyDict accessors; + LazyDict animations; + LazyDict buffers; + LazyDict bufferViews; + LazyDict cameras; + LazyDict images; + LazyDict materials; + LazyDict meshes; + LazyDict nodes; + //LazyDict programs; + //LazyDict samplers; + LazyDict scenes; + //LazyDict shaders; + //LazyDict skins; + //LazyDict techniques; + LazyDict textures; + + LazyDict lights; // KHR_materials_common ext + + Ref scene; + + public: + Asset(IOSystem* io = 0) + : mIOSystem(io) + , accessors (*this, "accessors") + , animations (*this, "animations") + , buffers (*this, "buffers") + , bufferViews (*this, "bufferViews") + , cameras (*this, "cameras") + , images (*this, "images") + , materials (*this, "materials") + , meshes (*this, "meshes") + , nodes (*this, "nodes") + //, programs (*this, "programs") + //, samplers (*this, "samplers") + , scenes (*this, "scenes") + //, shaders (*this, "shaders") + //, skins (*this, "skins") + //, techniques (*this, "techniques") + , textures (*this, "textures") + , lights (*this, "lights", "KHR_materials_common") + { + memset(&extensionsUsed, 0, sizeof(extensionsUsed)); + memset(&asset, 0, sizeof(asset)); + } + + //! Main function + void Load(const std::string& file, bool isBinary = false); + + //! Enables the "KHR_binary_glTF" extension on the asset + void SetAsBinary(); + + //! Search for an available name, starting from the given strings + std::string FindUniqueID(const std::string& str, const char* suffix); + + Ref GetBodyBuffer() + { return mBodyBuffer; } + + private: + void ReadBinaryHeader(IOStream& stream); + + void ReadExtensionsUsed(Document& doc); + + + IOStream* OpenFile(std::string path, const char* mode, bool absolute = false); + }; + +} + +// Include the implementation of the methods +#include "glTFAsset.inl" + +#endif diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl new file mode 100644 index 000000000..82f7a92f3 --- /dev/null +++ b/code/glTFAsset.inl @@ -0,0 +1,1212 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +namespace glTF { + +namespace { + + // + // JSON Value reading helpers + // + + template + struct ReadHelper { static bool Read(Value& val, T& out) { + return val.IsInt() ? out = static_cast(val.GetInt()), true : false; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, bool& out) { + return val.IsBool() ? out = val.GetBool(), true : false; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, float& out) { + return val.IsNumber() ? out = static_cast(val.GetDouble()), true : false; + }}; + + template struct ReadHelper { static bool Read(Value& val, float (&out)[N]) { + if (!val.IsArray() || val.Size() != N) return false; + for (int i = 0; i < N; ++i) { + if (val[i].IsNumber()) + out[i] = static_cast(val[i].GetDouble()); + } + return true; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, const char*& out) { + return val.IsString() ? out = val.GetString(), true : false; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, std::string& out) { + return val.IsString() ? out = val.GetString(), true : false; + }}; + + template struct ReadHelper< Nullable > { static bool Read(Value& val, Nullable& out) { + return out.isPresent = ReadHelper::Read(val, out.value); + }}; + + template + inline static bool ReadValue(Value& val, T& out) + { + return ReadHelper::Read(val, out); + } + + template + inline static bool ReadMember(Value& obj, const char* id, T& out) + { + Value::MemberIterator it = obj.FindMember(id); + if (it != obj.MemberEnd()) { + return ReadHelper::Read(it->value, out); + } + return false; + } + + template + inline static T MemberOrDefault(Value& obj, const char* id, T defaultValue) + { + T out; + return ReadMember(obj, id, out) ? out : defaultValue; + } + + inline Value* FindMember(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd()) ? &it->value : 0; + } + + inline Value* FindString(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; + } + + inline Value* FindArray(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : 0; + } + + inline Value* FindObject(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : 0; + } +} + +// +// LazyDict methods +// + +template +inline LazyDict::LazyDict(Asset& asset, const char* dictId, const char* extId) + : mDictId(dictId), mExtId(extId), mDict(0), mAsset(asset) +{ + asset.mDicts.push_back(this); // register to the list of dictionaries +} + +template +inline LazyDict::~LazyDict() +{ + for (size_t i = 0; i < mObjs.size(); ++i) { + delete mObjs[i]; + } +} + + +template +inline void LazyDict::AttachToDocument(Document& doc) +{ + Value* container = 0; + + if (mExtId) { + if (Value* exts = FindObject(doc, "extensions")) { + container = FindObject(*exts, mExtId); + } + } + else { + container = &doc; + } + + if (container) { + mDict = FindObject(*container, mDictId); + } +} + +template +inline void LazyDict::DetachFromDocument() +{ + mDict = 0; +} + +template +Ref LazyDict::Get(size_t i) +{ + return Ref(mObjs, i); +} + +template +Ref LazyDict::Get(const char* id) +{ + typename Dict::iterator it = mObjsById.find(id); + if (it != mObjsById.end()) { // already created? + return Ref(mObjs, it->second); + } + + // read it from the JSON object + if (!mDict) { + return Ref(); // section is missing + } + + Value::MemberIterator obj = mDict->FindMember(id); + if (obj == mDict->MemberEnd()) { + throw DeadlyImportError("Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\""); + } + if (!obj->value.IsObject()) { + throw DeadlyImportError("Object with id \"" + std::string(id) + "\" is not a JSON object!"); + } + + // create an instance of the given type + T* inst = new T(); + inst->id = id; + ReadMember(obj->value, "name", inst->name); + inst->Read(obj->value, mAsset); + return Add(inst); +} + +template +Ref LazyDict::Add(T* obj) +{ + size_t idx = mObjs.size(); + mObjs.push_back(obj); + mObjsById[obj->id] = idx; + mAsset.mUsedIds[obj->id] = true; + return Ref(mObjs, idx); +} + +template +Ref LazyDict::Create(const char* id) +{ + Asset::IdMap::iterator it = mAsset.mUsedIds.find(id); + if (it != mAsset.mUsedIds.end()) { + throw DeadlyImportError("Two objects with the same ID exist!"); + } + T* inst = new T(); + inst->id = id; + return Add(inst); +} + + +// +// glTF dictionary objects methods +// + + +inline Buffer::Buffer() +: byteLength(0), type(Type_arraybuffer), mIsSpecial(false) +{ } + + +inline void Buffer::Read(Value& obj, Asset& r) +{ + size_t statedLength = MemberOrDefault(obj, "byteLength", 0); + byteLength = statedLength; + + Value* it = FindString(obj, "uri"); + if (!it) return; + + const char* uri = it->GetString(); + + Util::DataURI dataURI; + if (ParseDataURI(uri, it->GetStringLength(), dataURI)) { + if (dataURI.base64) { + uint8_t* data = 0; + this->byteLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, data); + this->mData.reset(data); + + if (statedLength > 0 && this->byteLength != statedLength) { + // error? + } + } + } + else { // Local file + if (byteLength > 0) { + IOStream* file = r.OpenFile(uri, "rb"); + if (file) { + LoadFromStream(*file, byteLength); + delete file; + } + } + } +} + +inline void Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseOffset) +{ + byteLength = length ? length : stream.FileSize(); + + if (baseOffset) { + stream.Seek(baseOffset, aiOrigin_SET); + } + + mData.reset(new uint8_t[byteLength]); + + if (stream.Read(mData.get(), byteLength, 1) != 1) { + throw DeadlyImportError("Unable to load buffer from file!"); + } +} + +inline size_t Buffer::AppendData(uint8_t* data, size_t length) +{ + size_t offset = this->byteLength; + Grow(length); + memcpy(mData.get() + offset, data, length); + return offset; +} + +inline void Buffer::Grow(size_t amount) +{ + if (amount <= 0) return; + uint8_t* b = new uint8_t[byteLength + amount]; + if (mData) memcpy(b, mData.get(), byteLength); + mData.reset(b); + byteLength += amount; +} + + +inline void BufferView::Read(Value& obj, Asset& r) +{ + const char* bufferId = MemberOrDefault(obj, "buffer", 0); + if (bufferId) { + buffer = r.buffers.Get(bufferId); + } + + byteOffset = MemberOrDefault(obj, "byteOffset", 0u); + byteLength = MemberOrDefault(obj, "byteLength", 0u); +} + + + +inline void Accessor::Read(Value& obj, Asset& r) +{ + const char* bufferViewId = MemberOrDefault(obj, "bufferView", 0); + if (bufferViewId) { + bufferView = r.bufferViews.Get(bufferViewId); + } + + byteOffset = MemberOrDefault(obj, "byteOffset", 0u); + byteStride = MemberOrDefault(obj, "byteStride", 0u); + componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); + count = MemberOrDefault(obj, "count", 0u); + + const char* typestr; + type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; +} + +inline unsigned int Accessor::GetNumComponents() +{ + return AttribType::GetNumComponents(type); +} + +inline unsigned int Accessor::GetBytesPerComponent() +{ + return ComponentTypeSize(componentType); +} + +inline unsigned int Accessor::GetElementSize() +{ + return GetNumComponents() * GetBytesPerComponent(); +} + +inline uint8_t* Accessor::GetPointer() +{ + if (!bufferView || !bufferView->buffer) return 0; + + size_t offset = byteOffset + bufferView->byteOffset; + return bufferView->buffer->GetPointer() + offset; +} + +namespace { + inline void CopyData(size_t count, + const uint8_t* src, size_t src_stride, + uint8_t* dst, size_t dst_stride) + { + if (src_stride == dst_stride) { + memcpy(dst, src, count * src_stride); + } + else { + size_t sz = std::min(src_stride, dst_stride); + for (size_t i = 0; i < count; ++i) { + memcpy(dst, src, sz); + if (sz < dst_stride) { + memset(dst + sz, 0, dst_stride - sz); + } + src += src_stride; + dst += dst_stride; + } + } + } +} + +template +void Accessor::ExtractData(T*& outData) +{ + uint8_t* data = GetPointer(); + ai_assert(data); + + const size_t elemSize = GetElementSize(); + const size_t totalSize = elemSize * count; + + const size_t stride = byteStride ? byteStride : elemSize; + + const size_t targetElemSize = sizeof(T); + ai_assert(elemSize <= targetElemSize); + + ai_assert(count*stride <= bufferView->byteLength); + + outData = new T[count]; + if (stride == elemSize && targetElemSize == elemSize) { + memcpy(outData, data, totalSize); + } + else { + for (size_t i = 0; i < count; ++i) { + memcpy(outData + i, data + i*stride, elemSize); + } + } +} + +inline void Accessor::WriteData(size_t count, const void* src_buffer, size_t src_stride) +{ + uint8_t* buffer_ptr = bufferView->buffer->GetPointer(); + size_t offset = byteOffset + bufferView->byteOffset; + + size_t dst_stride = GetNumComponents() * GetBytesPerComponent(); + + const uint8_t* src = reinterpret_cast(src_buffer); + uint8_t* dst = reinterpret_cast< uint8_t*>(buffer_ptr + offset); + + ai_assert(dst + count*dst_stride <= buffer_ptr + bufferView->buffer->byteLength); + CopyData(count, src, src_stride, dst, dst_stride); +} + + + +inline Accessor::Indexer::Indexer(Accessor& acc) + : accessor(acc) + , data(acc.GetPointer()) + , elemSize(acc.GetElementSize()) + , stride(acc.byteStride ? acc.byteStride : elemSize) +{ + +} + +//! Accesses the i-th value as defined by the accessor +template +T Accessor::Indexer::GetValue(int i) +{ + ai_assert(data); + ai_assert(i*stride < accessor.bufferView->byteLength); + T value = T(); + memcpy(&value, data + i*stride, elemSize); + //value >>= 8 * (sizeof(T) - elemSize); + return value; +} + +inline Image::Image() + : mData(0) + , mDataLength(0) +{ + +} + +inline void Image::Read(Value& obj, Asset& r) +{ + // Check for extensions first (to detect binary embedded data) + if (Value* extensions = FindObject(obj, "extensions")) { + if (r.extensionsUsed.KHR_binary_glTF) { + if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) { + + int width = MemberOrDefault(*ext, "width", 0); + int height = MemberOrDefault(*ext, "height", 0); + + ReadMember(*ext, "mimeType", mimeType); + + const char* bufferViewId; + if (ReadMember(*ext, "bufferView", bufferViewId)) { + Ref bv = r.bufferViews.Get(bufferViewId); + if (bv) { + mDataLength = bv->byteLength; + mData = new uint8_t[mDataLength]; + memcpy(mData, bv->buffer->GetPointer() + bv->byteOffset, mDataLength); + } + } + } + } + } + + if (!mDataLength) { + if (Value* uri = FindString(obj, "uri")) { + const char* uristr = uri->GetString(); + + Util::DataURI dataURI; + if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) { + mimeType = dataURI.mediaType; + if (dataURI.base64) { + mDataLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, mData); + } + } + else { + this->uri = uristr; + } + } + } +} + +inline uint8_t* Image::StealData() +{ + uint8_t* data = mData; + mDataLength = 0; + mData = 0; + return data; +} + +inline void Image::SetData(uint8_t* data, size_t length, Asset& r) +{ + Ref b = r.GetBodyBuffer(); + if (b) { // binary file: append to body + std::string bvId = r.FindUniqueID(this->id, "imgdata"); + bufferView = r.bufferViews.Create(bvId); + + bufferView->buffer = b; + bufferView->byteLength = length; + bufferView->byteOffset = b->AppendData(data, length); + } + else { // text file: will be stored as a data uri + this->mData = data; + this->mDataLength = length; + } +} + +inline void Texture::Read(Value& obj, Asset& r) +{ + const char* sourcestr; + if (ReadMember(obj, "source", sourcestr)) { + source = r.images.Get(sourcestr); + } +} + +namespace { + inline void ReadMaterialProperty(Asset& r, Value& vals, const char* propName, TexProperty& out) + { + if (Value* prop = FindMember(vals, propName)) { + if (prop->IsString()) { + out.texture = r.textures.Get(prop->GetString()); + } + else { + ReadValue(*prop, out.color); + } + } + } +} + +inline void Material::Read(Value& material, Asset& r) +{ + SetDefaults(); + + if (Value* values = FindObject(material, "values")) { + ReadMaterialProperty(r, *values, "ambient", this->ambient); + ReadMaterialProperty(r, *values, "diffuse", this->diffuse); + ReadMaterialProperty(r, *values, "specular", this->specular); + + ReadMember(*values, "shininess", shininess); + } + + if (Value* extensions = FindObject(material, "extensions")) { + if (r.extensionsUsed.KHR_materials_common) { + if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { + if (Value* tnq = FindString(*ext, "technique")) { + const char* t = tnq->GetString(); + if (strcmp(t, "BLINN") == 0) technique = Technique_BLINN; + else if (strcmp(t, "PHONG") == 0) technique = Technique_PHONG; + else if (strcmp(t, "LAMBERT") == 0) technique = Technique_LAMBERT; + else if (strcmp(t, "CONSTANT") == 0) technique = Technique_CONSTANT; + } + + ReadMaterialProperty(r, *ext, "ambient", this->ambient); + ReadMaterialProperty(r, *ext, "diffuse", this->diffuse); + ReadMaterialProperty(r, *ext, "specular", this->specular); + + ReadMember(*ext, "doubleSided", doubleSided); + ReadMember(*ext, "transparent", transparent); + ReadMember(*ext, "transparency", transparency); + ReadMember(*ext, "shininess", shininess); + } + } + } +} + +namespace { + void SetVector(vec4& v, float x, float y, float z, float w) + { v[0] = x; v[1] = y; v[2] = z; v[3] = w; } +} + +inline void Material::SetDefaults() +{ + SetVector(ambient.color, 0, 0, 0, 1); + SetVector(diffuse.color, 0, 0, 0, 1); + SetVector(specular.color, 0, 0, 0, 1); + SetVector(emission.color, 0, 0, 0, 1); + + doubleSided = false; + transparent = false; + transparency = 1.0; + shininess = 0.0; + + technique = Technique_undefined; +} + +namespace { + + template + inline int Compare(const char* attr, const char (&str)[N]) { + return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; + } + + inline bool GetAttribVector(Mesh::Primitive& p, const char* attr, Mesh::AccessorList*& v, int& pos) + { + if (pos = Compare(attr, "POSITION")) { + v = &(p.attributes.position); + } + else if (pos = Compare(attr, "NORMAL")) { + v = &(p.attributes.normal); + } + else if (pos = Compare(attr, "TEXCOORD")) { + v = &(p.attributes.texcoord); + } + else if (pos = Compare(attr, "COLOR")) { + v = &(p.attributes.color); + } + else if (pos = Compare(attr, "JOINT")) { + v = &(p.attributes.joint); + } + else if (pos = Compare(attr, "JOINTMATRIX")) { + v = &(p.attributes.jointmatrix); + } + else if (pos = Compare(attr, "WEIGHT")) { + v = &(p.attributes.weight); + } + else return false; + return true; + } +} + +inline void Mesh::Read(Value& obj, Asset& r) +{ + if (Value* primitives = FindArray(obj, "primitives")) { + this->primitives.resize(primitives->Size()); + for (unsigned int i = 0; i < primitives->Size(); ++i) { + Value& primitive = (*primitives)[i]; + + Primitive& prim = this->primitives[i]; + prim.mode = MemberOrDefault(primitive, "mode", PrimitiveMode_TRIANGLES); + + if (Value* attrs = FindObject(primitive, "attributes")) { + for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) { + if (!it->value.IsString()) continue; + const char* attr = it->name.GetString(); + // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. + + int undPos = 0; + Mesh::AccessorList* vec = 0; + if (GetAttribVector(prim, attr, vec, undPos)) { + size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; + if ((*vec).size() <= idx) (*vec).resize(idx + 1); + (*vec)[idx] = r.accessors.Get(it->value.GetString()); + } + } + } + + if (Value* indices = FindString(primitive, "indices")) { + prim.indices = r.accessors.Get(indices->GetString()); + } + + if (Value* material = FindString(primitive, "material")) { + prim.material = r.materials.Get(material->GetString()); + } + } + } +} + + +inline void Camera::Read(Value& obj, Asset& r) +{ + type = MemberOrDefault(obj, "type", Camera::Perspective); + + const char* subobjId = (type == Camera::Orthographic) ? "ortographic" : "perspective"; + + Value* it = FindObject(obj, subobjId); + if (!it) throw DeadlyImportError("Camera missing its parameters!"); + + if (type == Camera::Perspective) { + perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f); + perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f); + perspective.zfar = MemberOrDefault(*it, "zfar", 100.f); + perspective.znear = MemberOrDefault(*it, "znear", 0.01f); + } + else { + ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f); + ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f); + ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f); + ortographic.znear = MemberOrDefault(obj, "znear", 0.01f); + } +} + +inline void Light::Read(Value& obj, Asset& r) +{ + SetDefaults(); + + if (Value* type = FindString(obj, "type")) { + const char* t = type->GetString(); + if (strcmp(t, "ambient") == 0) this->type = Type_ambient; + else if (strcmp(t, "directional") == 0) this->type = Type_directional; + else if (strcmp(t, "point") == 0) this->type = Type_point; + else if (strcmp(t, "spot") == 0) this->type = Type_spot; + + if (this->type != Type_undefined) { + if (Value* vals = FindString(obj, t)) { + ReadMember(*vals, "color", color); + + ReadMember(*vals, "constantAttenuation", constantAttenuation); + ReadMember(*vals, "linearAttenuation", linearAttenuation); + ReadMember(*vals, "quadraticAttenuation", quadraticAttenuation); + ReadMember(*vals, "distance", distance); + + ReadMember(*vals, "falloffAngle", falloffAngle); + ReadMember(*vals, "falloffExponent", falloffExponent); + } + } + } +} + +inline void Light::SetDefaults() +{ + #ifndef M_PI + const float M_PI = 3.14159265358979323846f; + #endif + + type = Type_undefined; + + SetVector(color, 0.f, 0.f, 0.f, 1.f); + + constantAttenuation = 0.f; + linearAttenuation = 1.f; + quadraticAttenuation = 1.f; + distance = 0.f; + + falloffAngle = static_cast(M_PI / 2.f); + falloffExponent = 0.f; +} + +inline void Node::Read(Value& obj, Asset& r) +{ + if (Value* children = FindArray(obj, "children")) { + this->children.reserve(children->Size()); + for (unsigned int i = 0; i < children->Size(); ++i) { + Value& child = (*children)[i]; + if (child.IsString()) { + // get/create the child node + Ref chn = r.nodes.Get(child.GetString()); + if (chn) this->children.push_back(chn); + } + } + } + + + if (Value* matrix = FindArray(obj, "matrix")) { + ReadValue(*matrix, this->matrix); + } + else { + ReadMember(obj, "translation", translation); + ReadMember(obj, "scale", scale); + ReadMember(obj, "rotation", rotation); + } + + if (Value* meshes = FindArray(obj, "meshes")) { + size_t numMeshes = (size_t)meshes->Size(); + + std::vector meshList; + + this->meshes.reserve(numMeshes); + for (size_t i = 0; i < numMeshes; ++i) { + if ((*meshes)[i].IsString()) { + Ref mesh = r.meshes.Get((*meshes)[i].GetString()); + if (mesh) this->meshes.push_back(mesh); + } + } + } + + if (Value* camera = FindString(obj, "camera")) { + this->camera = r.cameras.Get(camera->GetString()); + if (this->camera) + this->camera->id = this->id; + } + + // TODO load "skeletons", "skin", "jointName" + + if (Value* extensions = FindObject(obj, "extensions")) { + if (r.extensionsUsed.KHR_materials_common) { + + if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { + if (Value* light = FindString(*ext, "light")) { + this->light = r.lights.Get(light->GetString()); + } + } + + } + } +} + +inline void Scene::Read(Value& obj, Asset& r) +{ + if (Value* array = FindArray(obj, "nodes")) { + for (unsigned int i = 0; i < array->Size(); ++i) { + if (!(*array)[i].IsString()) continue; + Ref node = r.nodes.Get((*array)[i].GetString()); + if (node) + this->nodes.push_back(node); + } + } +} + + +inline void AssetMetadata::Read(Document& doc) +{ + // read the version, etc. + int statedVersion = 0; + if (Value* obj = FindObject(doc, "asset")) { + ReadMember(*obj, "copyright", copyright); + ReadMember(*obj, "generator", generator); + + premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); + statedVersion = MemberOrDefault(*obj, "version", 0); + + if (Value* profile = FindObject(*obj, "profile")) { + ReadMember(*profile, "api", this->profile.api); + ReadMember(*profile, "version", this->profile.version); + } + } + + version = std::max(statedVersion, version); + if (version == 0) { + // if missing version, we'll assume version 1... + version = 1; + } + + if (version != 1) { + char msg[128]; + sprintf(msg, "Unsupported glTF version: %d", version); + throw DeadlyImportError(msg); + } +} + + + +// +// Asset methods implementation +// + +inline void Asset::ReadBinaryHeader(IOStream& stream) +{ + GLB_Header header; + if (stream.Read(&header, sizeof(header), 1) != 1) { + throw DeadlyImportError("Unable to read the file header"); + } + + if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) { + throw DeadlyImportError("Invalid binary glTF file"); + } + + AI_SWAP4(header.version); + asset.version = header.version; + if (header.version != 1) { + throw DeadlyImportError("Unsupported binary glTF version"); + } + + AI_SWAP4(header.sceneFormat); + if (header.sceneFormat != SceneFormat_JSON) { + throw DeadlyImportError("Unsupported binary glTF scene format"); + } + + AI_SWAP4(header.length); + AI_SWAP4(header.sceneLength); + + mSceneLength = static_cast(header.sceneLength); + + mBodyOffset = sizeof(header)+mSceneLength; + mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4 + + mBodyLength = header.length - mBodyOffset; +} + +inline void Asset::Load(const std::string& pFile, bool isBinary) +{ + mCurrentAssetDir.clear(); + int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); + if (pos != int(std::string::npos)) mCurrentAssetDir = pFile.substr(0, pos + 1); + + shared_ptr stream(OpenFile(pFile.c_str(), "rb", true)); + if (!stream) { + throw DeadlyImportError("Could not open file for reading"); + } + + // is binary? then read the header + if (isBinary) { + SetAsBinary(); // also creates the body buffer + ReadBinaryHeader(*stream); + } + else { + mSceneLength = stream->FileSize(); + mBodyLength = 0; + } + + + // read the scene data + + std::vector sceneData(mSceneLength + 1); + sceneData[mSceneLength] = '\0'; + + if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { + throw DeadlyImportError("Could not read the file contents"); + } + + + // parse the JSON document + + Document doc; + doc.ParseInsitu(&sceneData[0]); + + if (doc.HasParseError()) { + char buffer[32]; + sprintf(buffer, "%u", doc.GetErrorOffset()); + throw DeadlyImportError(std::string("JSON parse error, offset ") + buffer + ": " + + GetParseError_En(doc.GetParseError())); + } + + if (!doc.IsObject()) { + throw DeadlyImportError("gltf file must be a JSON object!"); + } + + // Fill the buffer instance for the current file embedded contents + if (mBodyLength > 0) { + mBodyBuffer->LoadFromStream(*stream, mBodyLength, mBodyOffset); + } + + + // Load the metadata + asset.Read(doc); + ReadExtensionsUsed(doc); + + // Prepare the dictionaries + for (size_t i = 0; i < mDicts.size(); ++i) { + mDicts[i]->AttachToDocument(doc); + } + + + + // Read the "scene" property, which specifies which scene to load + // and recursively load everything referenced by it + if (Value* scene = FindString(doc, "scene")) { + this->scene = scenes.Get(scene->GetString()); + } + + // Clean up + for (size_t i = 0; i < mDicts.size(); ++i) { + mDicts[i]->DetachFromDocument(); + } +} + +inline void Asset::SetAsBinary() +{ + if (!extensionsUsed.KHR_binary_glTF) { + extensionsUsed.KHR_binary_glTF = true; + mBodyBuffer = buffers.Create("KHR_binary_glTF"); + mBodyBuffer->MarkAsSpecial(); + } +} + + +inline void Asset::ReadExtensionsUsed(Document& doc) +{ + Value* extsUsed = FindArray(doc, "extensionsUsed"); + if (!extsUsed) return; + + std::gltf_unordered_map exts; + + for (unsigned int i = 0; i < extsUsed->Size(); ++i) { + if ((*extsUsed)[i].IsString()) { + exts[(*extsUsed)[i].GetString()] = true; + } + } + + #define CHECK_EXT(EXT) \ + if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; + + CHECK_EXT(KHR_binary_glTF); + CHECK_EXT(KHR_materials_common); + + #undef CHECK_EXT +} + +inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool absolute) +{ + #ifdef ASSIMP_API + return mIOSystem->Open(path, mode); + #else + if (path.size() < 2) return 0; + if (!absolute && path[1] != ':' && path[0] != '/') { // relative? + path = mCurrentAssetDir + path; + } + FILE* f = fopen(path.c_str(), mode); + return f ? new IOStream(f) : 0; + #endif +} + +inline std::string Asset::FindUniqueID(const std::string& str, const char* suffix) +{ + std::string id = str; + + Asset::IdMap::iterator it; + + do { + if (!id.empty()) { + it = mUsedIds.find(id); + if (it == mUsedIds.end()) break; + + id += "_"; + } + + id += suffix; + + it = mUsedIds.find(id); + if (it == mUsedIds.end()) break; + + char buffer[256]; + int offset = sprintf(buffer, "%s_", id.c_str()); + for (int i = 0; it != mUsedIds.end(); ++i) { + sprintf(buffer + offset, "%d", i); + + id = buffer; + it = mUsedIds.find(id); + } + } while (false); // fake loop to allow using "break" + + return id; +} + +namespace Util +{ + + inline bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) + { + if (const_uri[0] != 0x10) { // we already parsed this uri? + if (strncmp(const_uri, "data:", 5) != 0) // not a data uri? + return false; + } + + // set defaults + out.mediaType = "text/plain"; + out.charset = "US-ASCII"; + out.base64 = false; + + char* uri = const_cast(const_uri); + if (uri[0] != 0x10) { + uri[0] = 0x10; + uri[1] = uri[2] = uri[3] = uri[4] = 0; + + size_t i = 5, j; + if (uri[i] != ';' && uri[i] != ',') { // has media type? + uri[1] = i; + for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {} + } + while (uri[i] == ';' && i < uriLen) { + uri[i++] = '\0'; + for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {} + + if (strncmp(uri + j, "charset=", 8) == 0) uri[2] = j + 8; + else if (strncmp(uri + j, "base64", 6) == 0) uri[3] = j; + } + if (i < uriLen) { + uri[i++] = '\0'; + uri[4] = i; + } + else { + uri[1] = uri[2] = uri[3] = 0; + uri[4] = 5; + } + } + + if (uri[1] != 0) out.mediaType = uri + uri[1]; + if (uri[2] != 0) out.charset = uri + uri[2]; + if (uri[3] != 0) out.base64 = true; + out.data = uri + uri[4]; + out.dataLength = (uri + uriLen) - out.data; + + return true; + } + + template + struct DATA + { + static const uint8_t tableDecodeBase64[128]; + }; + + template + const uint8_t DATA::tableDecodeBase64[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0 + }; + + inline char EncodeCharBase64(uint8_t b) + { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[b]; + } + + inline uint8_t DecodeCharBase64(char c) + { + return DATA::tableDecodeBase64[c]; // TODO faster with lookup table or ifs? + /*if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + if (c == '+') return 62; + if (c == '/') return 63; + return 64; // '-' */ + } + + inline size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out) + { + ai_assert(inLength % 4 == 0); + + if (inLength < 4) { + out = 0; + return 0; + } + + int nEquals = int(in[inLength - 1] == '=') + + int(in[inLength - 2] == '='); + + size_t outLength = (inLength * 3) / 4 - nEquals; + out = new uint8_t[outLength]; + memset(out, 0, outLength); + + size_t i, j = 0; + + for (i = 0; i + 4 < inLength; i += 4) { + uint8_t b0 = DecodeCharBase64(in[i]); + uint8_t b1 = DecodeCharBase64(in[i + 1]); + uint8_t b2 = DecodeCharBase64(in[i + 2]); + uint8_t b3 = DecodeCharBase64(in[i + 3]); + + out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4)); + out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2)); + out[j++] = (uint8_t)((b2 << 6) | b3); + } + + { + uint8_t b0 = DecodeCharBase64(in[i]); + uint8_t b1 = DecodeCharBase64(in[i + 1]); + uint8_t b2 = DecodeCharBase64(in[i + 2]); + uint8_t b3 = DecodeCharBase64(in[i + 3]); + + out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4)); + if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2)); + if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3); + } + + return outLength; + } + + + + inline void EncodeBase64( + const uint8_t* in, size_t inLength, + std::string& out) + { + size_t outLength = ((inLength + 2) / 3) * 4; + + size_t j = out.size(); + out.resize(j + outLength); + + for (size_t i = 0; i < inLength; i += 3) { + uint8_t b = (in[i] & 0xFC) >> 2; + out[j++] = EncodeCharBase64(b); + + b = (in[i] & 0x03) << 4; + if (i + 1 < inLength) { + b |= (in[i + 1] & 0xF0) >> 4; + out[j++] = EncodeCharBase64(b); + + b = (in[i + 1] & 0x0F) << 2; + if (i + 2 < inLength) { + b |= (in[i + 2] & 0xC0) >> 6; + out[j++] = EncodeCharBase64(b); + + b = in[i + 2] & 0x3F; + out[j++] = EncodeCharBase64(b); + } + else { + out[j++] = EncodeCharBase64(b); + out[j++] = '='; + } + } + else { + out[j++] = EncodeCharBase64(b); + out[j++] = '='; + out[j++] = '='; + } + } + } + +} + +} + + diff --git a/code/glTFUtil.h b/code/glTFAssetWriter.h similarity index 62% rename from code/glTFUtil.h rename to code/glTFAssetWriter.h index 089632ca1..65d05320c 100644 --- a/code/glTFUtil.h +++ b/code/glTFAssetWriter.h @@ -37,49 +37,47 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -#ifndef AI_GLTFUTIL_H_INC -#define AI_GLTFUTIL_H_INC -//#include "StreamReader.h" -//#include "MemoryIOWrapper.h" -#include "StringComparison.h" +/** @file glTFWriter.h + * Declares a class to write gltf/glb files + * + * glTF Extensions Support: + * KHR_binary_glTF: full + * KHR_materials_common: full + */ +#ifndef glTFAssetWriter_H_INC +#define glTFAssetWriter_H_INC -#if _MSC_VER > 1500 || (defined __GNUC___) -# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP -# else -# define gltf_unordered_map map -# define gltf_unordered_multimap multimap -#endif +#include "glTFAsset.h" -#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP -# include -# if _MSC_VER > 1600 -# define gltf_unordered_map unordered_map -# define gltf_unordered_multimap unordered_multimap -# else -# define gltf_unordered_map tr1::unordered_map -# define gltf_unordered_multimap tr1::unordered_multimap -# endif -#endif +namespace glTF +{ -namespace Assimp { -namespace glTF { +using rapidjson::MemoryPoolAllocator; - // - // Misc - // +class AssetWriter +{ +private: - std::size_t DecodeBase64(const char* in, uint8_t*& out); - std::size_t DecodeBase64(const char* in, std::size_t inLength, uint8_t*& out); + void WriteBinaryData(IOStream* outfile, size_t sceneLength); - void EncodeBase64(const uint8_t* in, std::size_t inLength, std::string& out); + void WriteMetadata(); + void WriteExtensionsUsed(); +public: + Document mDoc; + Asset& mAsset; - bool IsDataURI(const char* uri); + MemoryPoolAllocator<>& mAl; + + AssetWriter(Asset& asset); + + void WriteFile(const char* path); +}; } -} +// Include the implementation of the methods +#include "glTFAssetWriter.inl" -#endif // AI_GLTFUTIL_H_INC - +#endif diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl new file mode 100644 index 000000000..d6e313f93 --- /dev/null +++ b/code/glTFAssetWriter.inl @@ -0,0 +1,490 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#include +#include +#include + +namespace glTF { + + using rapidjson::StringBuffer; + using rapidjson::PrettyWriter; + using rapidjson::Writer; + using rapidjson::StringRef; + using rapidjson::StringRef; + + namespace { + + template + inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) { + val.SetArray(); + val.Reserve(N, al); + for (int i = 0; i < N; ++i) { + val.PushBack(r[i], al); + } + return val; + }; + + template + inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref >& v, MemoryPoolAllocator<>& al) { + if (v.empty()) return; + Value lst; + lst.SetArray(); + lst.Reserve(v.size(), al); + for (size_t i = 0; i < v.size(); ++i) { + lst.PushBack(StringRef(v[i]->id), al); + } + obj.AddMember(StringRef(fieldId), lst, al); + }; + + + } + + inline void Write(Value& obj, Accessor& a, AssetWriter& w) + { + obj.AddMember("bufferView", Value(a.bufferView->id, w.mAl).Move(), w.mAl); + obj.AddMember("byteOffset", a.byteOffset, w.mAl); + obj.AddMember("byteStride", a.byteStride, w.mAl); + obj.AddMember("componentType", int(a.componentType), w.mAl); + obj.AddMember("count", a.count, w.mAl); + obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); + } + + inline void Write(Value& obj, Animation& a, AssetWriter& w) + { + + } + + inline void Write(Value& obj, Buffer& b, AssetWriter& w) + { + std::string dataURI = "data:application/octet-stream;base64,"; + Util::EncodeBase64(b.GetPointer(), b.byteLength, dataURI); + + const char* type; + switch (b.type) { + case Buffer::Type_text: + type = "text"; break; + default: + type = "arraybuffer"; + } + + obj.AddMember("byteLength", b.byteLength, w.mAl); + obj.AddMember("type", StringRef(type), w.mAl); + obj.AddMember("uri", Value(dataURI, w.mAl).Move(), w.mAl); + } + + inline void Write(Value& obj, BufferView& bv, AssetWriter& w) + { + obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl); + obj.AddMember("byteOffset", bv.byteOffset, w.mAl); + obj.AddMember("byteLength", bv.byteLength, w.mAl); + obj.AddMember("target", int(bv.target), w.mAl); + } + + inline void Write(Value& obj, Camera& c, AssetWriter& w) + { + + } + + inline void Write(Value& obj, Image& img, AssetWriter& w) + { + std::string uri; + if (w.mAsset.extensionsUsed.KHR_binary_glTF && img.bufferView) { + Value exts, ext; + exts.SetObject(); + ext.SetObject(); + + ext.AddMember("bufferView", StringRef(img.bufferView->id), w.mAl); + + if (!img.mimeType.empty()) + ext.AddMember("mimeType", StringRef(img.mimeType), w.mAl); + + exts.AddMember("KHR_binary_glTF", ext, w.mAl); + obj.AddMember("extensions", exts, w.mAl); + return; + } + else if (img.HasData()) { + uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType); + uri += ";base64,"; + Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri); + } + else { + uri = img.uri; + } + + obj.AddMember("uri", Value(uri, w.mAl).Move(), w.mAl); + } + + namespace { + inline void WriteColorOrTex(Value& obj, TexProperty& prop, const char* propName, MemoryPoolAllocator<>& al) + { + if (prop.texture) + obj.AddMember(StringRef(propName), Value(prop.texture->id, al).Move(), al); + else { + Value col; + obj.AddMember(StringRef(propName), MakeValue(col, prop.color, al), al); + } + } + } + + inline void Write(Value& obj, Material& m, AssetWriter& w) + { + Value v; + v.SetObject(); + { + WriteColorOrTex(v, m.ambient, "ambient", w.mAl); + WriteColorOrTex(v, m.diffuse, "diffuse", w.mAl); + WriteColorOrTex(v, m.specular, "specular", w.mAl); + WriteColorOrTex(v, m.emission, "emission", w.mAl); + + v.AddMember("shininess", m.shininess, w.mAl); + } + obj.AddMember("values", v, w.mAl); + } + + namespace { + inline void WriteAttrs(AssetWriter& w, Value& attrs, Mesh::AccessorList& lst, + const char* semantic, bool forceNumber = false) + { + if (lst.empty()) return; + if (lst.size() == 1 && !forceNumber) { + attrs.AddMember(StringRef(semantic), Value(lst[0]->id, w.mAl).Move(), w.mAl); + } + else { + for (size_t i = 0; i < lst.size(); ++i) { + char buffer[32]; + sprintf(buffer, "%s_%d", semantic, i); + attrs.AddMember(Value(buffer, w.mAl).Move(), Value(lst[i]->id, w.mAl).Move(), w.mAl); + } + } + } + } + + inline void Write(Value& obj, Mesh& m, AssetWriter& w) + { + Value primitives; + primitives.SetArray(); + primitives.Reserve(m.primitives.size(), w.mAl); + + for (size_t i = 0; i < m.primitives.size(); ++i) { + Mesh::Primitive& p = m.primitives[i]; + Value prim; + prim.SetObject(); + { + prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl); + + if (p.material) + prim.AddMember("material", p.material->id, w.mAl); + + if (p.indices) + prim.AddMember("indices", Value(p.indices->id, w.mAl).Move(), w.mAl); + + Value attrs; + attrs.SetObject(); + { + WriteAttrs(w, attrs, p.attributes.position, "POSITION"); + WriteAttrs(w, attrs, p.attributes.normal, "NORMAL"); + WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true); + WriteAttrs(w, attrs, p.attributes.color, "COLOR"); + WriteAttrs(w, attrs, p.attributes.joint, "JOINT"); + WriteAttrs(w, attrs, p.attributes.jointmatrix, "JOINTMATRIX"); + WriteAttrs(w, attrs, p.attributes.weight, "WEIGHT"); + } + prim.AddMember("attributes", attrs, w.mAl); + } + primitives.PushBack(prim, w.mAl); + } + + obj.AddMember("primitives", primitives, w.mAl); + } + + inline void Write(Value& obj, Node& n, AssetWriter& w) + { + + if (n.matrix.isPresent) { + Value val; + obj.AddMember("matrix", MakeValue(val, n.matrix.value, w.mAl).Move(), w.mAl); + } + + if (n.translation.isPresent) { + Value val; + obj.AddMember("translation", MakeValue(val, n.translation.value, w.mAl).Move(), w.mAl); + } + + if (n.scale.isPresent) { + Value val; + obj.AddMember("scale", MakeValue(val, n.scale.value, w.mAl).Move(), w.mAl); + } + if (n.rotation.isPresent) { + Value val; + obj.AddMember("rotation", MakeValue(val, n.rotation.value, w.mAl).Move(), w.mAl); + } + + AddRefsVector(obj, "children", n.children, w.mAl); + + AddRefsVector(obj, "meshes", n.meshes, w.mAl); + } + + inline void Write(Value& obj, Program& b, AssetWriter& w) + { + + } + + inline void Write(Value& obj, Sampler& b, AssetWriter& w) + { + + } + + inline void Write(Value& scene, Scene& s, AssetWriter& w) + { + AddRefsVector(scene, "nodes", s.nodes, w.mAl); + } + + inline void Write(Value& obj, Shader& b, AssetWriter& w) + { + + } + + inline void Write(Value& obj, Skin& b, AssetWriter& w) + { + + } + + inline void Write(Value& obj, Technique& b, AssetWriter& w) + { + + } + + inline void Write(Value& obj, Texture& tex, AssetWriter& w) + { + if (tex.source) { + obj.AddMember("source", Value(tex.source->id, w.mAl).Move(), w.mAl); + } + } + + inline void Write(Value& obj, Light& b, AssetWriter& w) + { + + } + + template + void LazyDict::WriteObjects(AssetWriter& w) + { + if (mObjs.empty()) return; + + Value* container = &w.mDoc; + + if (mExtId) { + Value* exts = FindObject(w.mDoc, "extensions"); + if (!exts) { + w.mDoc.AddMember("extensions", Value().SetObject().Move(), w.mDoc.GetAllocator()); + exts = FindObject(w.mDoc, "extensions"); + } + + if (!(container = FindObject(*exts, mExtId))) { + exts->AddMember(StringRef(mExtId), Value().SetObject().Move(), w.mDoc.GetAllocator()); + container = FindObject(*exts, mExtId); + } + } + + Value* dict; + if (!(dict = FindObject(*container, mDictId))) { + container->AddMember(StringRef(mDictId), Value().SetObject().Move(), w.mDoc.GetAllocator()); + dict = FindObject(*container, mDictId); + } + + for (size_t i = 0; i < mObjs.size(); ++i) { + if (mObjs[i]->IsSpecial()) continue; + + Value obj; + obj.SetObject(); + + if (!mObjs[i]->name.empty()) { + obj.AddMember("name", StringRef(mObjs[i]->name.c_str()), w.mAl); + } + + Write(obj, *mObjs[i], w); + + dict->AddMember(StringRef(mObjs[i]->id), obj, w.mAl); + } + } + + + AssetWriter::AssetWriter(Asset& a) + : mAsset(a) + , mDoc() + , mAl(mDoc.GetAllocator()) + { + mDoc.SetObject(); + + WriteMetadata(); + WriteExtensionsUsed(); + + // Dump the contents of the dictionaries + for (size_t i = 0; i < a.mDicts.size(); ++i) { + a.mDicts[i]->WriteObjects(*this); + } + + // Add the target scene field + if (mAsset.scene) { + mDoc.AddMember("scene", StringRef(mAsset.scene->id), mAl); + } + } + + + void AssetWriter::WriteFile(const char* path) + { + bool isBinary = mAsset.extensionsUsed.KHR_binary_glTF; + + boost::scoped_ptr outfile + (mAsset.OpenFile(path, isBinary ? "wb" : "wt", true)); + + if (outfile == 0) { + throw DeadlyExportError("Could not open output file: " + std::string(path)); + } + + if (isBinary) { + // we will write the header later, skip its size + outfile->Seek(sizeof(GLB_Header), aiOrigin_SET); + } + + StringBuffer docBuffer; + + bool pretty = true; + if (!isBinary && pretty) { + PrettyWriter writer(docBuffer); + mDoc.Accept(writer); + } + else { + Writer writer(docBuffer); + mDoc.Accept(writer); + } + + if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { + throw DeadlyExportError("Failed to write scene data!"); + } + + if (isBinary) { + WriteBinaryData(outfile.get(), docBuffer.GetSize()); + } + } + + void AssetWriter::WriteBinaryData(IOStream* outfile, size_t sceneLength) + { + // + // write the body data + // + + size_t bodyLength = 0; + if (Ref b = mAsset.GetBodyBuffer()) { + bodyLength = b->byteLength; + + if (bodyLength > 0) { + size_t bodyOffset = sizeof(GLB_Header) + sceneLength; + bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4 + + outfile->Seek(bodyOffset, aiOrigin_SET); + + if (outfile->Write(b->GetPointer(), b->byteLength, 1) != 1) { + throw DeadlyExportError("Failed to write body data!"); + } + } + } + + + // + // write the header + // + + GLB_Header header; + memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)); + + header.version = 1; + AI_SWAP4(header.version); + + header.length = sizeof(header) + sceneLength + bodyLength; + AI_SWAP4(header.length); + + header.sceneLength = sceneLength; + AI_SWAP4(header.sceneLength); + + header.sceneFormat = SceneFormat_JSON; + AI_SWAP4(header.sceneFormat); + + outfile->Seek(0, aiOrigin_SET); + + if (outfile->Write(&header, 1, sizeof(header)) != sizeof(header)) { + throw DeadlyExportError("Failed to write the header!"); + } + } + + + void AssetWriter::WriteMetadata() + { + Value asset; + asset.SetObject(); + { + asset.AddMember("version", mAsset.asset.version, mAl); + + asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); + } + mDoc.AddMember("asset", asset, mAl); + } + + void AssetWriter::WriteExtensionsUsed() + { + Value exts; + exts.SetArray(); + { + if (false) + exts.PushBack(StringRef("KHR_binary_glTF"), mAl); + + if (false) + exts.PushBack(StringRef("KHR_materials_common"), mAl); + } + + if (!exts.Empty()) + mDoc.AddMember("extensionsUsed", exts, mAl); + } + + +} + + diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index eb133cccb..b47e0da24 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -56,20 +56,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include -#define RAPIDJSON_HAS_STDSTRING 1 -#include -#include -#include -#include - -#include "glTFFileData.h" -#include "glTFUtil.h" +#include "glTFAssetWriter.h" using namespace rapidjson; using namespace Assimp; -using namespace Assimp::glTF; +using namespace glTF; namespace Assimp { @@ -93,307 +87,279 @@ namespace Assimp { -class glTFSceneExporter -{ - typedef std::gltf_unordered_map IdMap; - - Document& mDoc; - MemoryPoolAllocator<>& mAl; - - const aiScene* mScene; - - std::string mRootNodeId; - - std::vector mMeshIds; - - IdMap mUsedIds; - -public: - glTFSceneExporter(Document& doc, const aiScene* pScene) - : mDoc(doc) - , mAl(doc.GetAllocator()) - , mScene(pScene) - { - doc.SetObject(); - - for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) { - - } - - for (unsigned int i = 0; i < pScene->mNumCameras; ++i) { - - } - - for (unsigned int i = 0; i < pScene->mNumLights; ++i) { - - } - - for (unsigned int i = 0; i < pScene->mNumLights; ++i) { - - } - - for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { - - } - - - AddMeshes(); - - for (unsigned int i = 0; i < pScene->mNumTextures; ++i) { - - } - - AddNodes(); - - CreateScene(); - } - - inline void Pushf(Value& val, float f) - { - val.PushBack(Value(f).Move(), mAl); - } - - inline void SetMatrix(Value& v, const aiMatrix4x4& m) - { - v.SetArray(); - v.Reserve(16, mAl); - - Pushf(v, m.a1); Pushf(v, m.b1); Pushf(v, m.c1); Pushf(v, m.d1); - Pushf(v, m.a2); Pushf(v, m.b2); Pushf(v, m.c2); Pushf(v, m.d2); - Pushf(v, m.a3); Pushf(v, m.b3); Pushf(v, m.c3); Pushf(v, m.d3); - Pushf(v, m.a4); Pushf(v, m.b4); Pushf(v, m.c4); Pushf(v, m.d4); - } - - void AddMeshes() - { - if (mScene->mNumMeshes == 0) return; - - Value meshes; - meshes.SetObject(); - - mMeshIds.reserve(mScene->mNumMeshes); - for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) { - aiMesh* m = mScene->mMeshes[i]; - std::string meshId = FindID(m->mName, "mesh"); - mMeshIds.push_back(meshId); - - Value mesh; - mesh.SetObject(); - { - Value primitives; - primitives.SetObject(); - - - mesh.AddMember("primitives", primitives, mAl); - } - - meshes.AddMember(StringRef(mMeshIds.back()), mesh, mAl); - } - - mDoc.AddMember("meshes", meshes, mAl); - } - - void AddNodes() - { - if (!mScene->mRootNode) return; - - Value nodes; - nodes.SetObject(); - - mRootNodeId = AddNode(nodes, mScene->mRootNode); - - mDoc.AddMember("nodes", nodes, mAl); - } - - - std::string AddNode(Value& nodes, const aiNode* n) - { - std::string nodeId = FindID(n->mName, "node"); - - Value node; - node.SetObject(); - - if (!n->mTransformation.IsIdentity()) { - Value matrix; - SetMatrix(matrix, n->mTransformation); - node.AddMember("matrix", matrix, mAl); - } - - if (n->mNumMeshes > 0) { - Value meshes; - meshes.SetArray(); - for (unsigned int i = 0; i < n->mNumMeshes; ++i) { - meshes.PushBack(StringRef(mMeshIds[n->mMeshes[i]]), mAl); - } - node.AddMember("meshes", meshes, mAl); - } - - if (n->mNumChildren > 0) { - Value children; - children.SetArray(); - for (unsigned int i = 0; i < n->mNumChildren; ++i) { - std::string id = AddNode(nodes, n->mChildren[i]); - children.PushBack(Value(id, mAl).Move(), mAl); - } - node.AddMember("children", children, mAl); - } - - nodes.AddMember(Value(nodeId, mAl).Move(), node, mAl); - - return nodeId; - } - - void CreateScene() - { - const char* sceneName = "defaultScene"; - - mDoc.AddMember("scene", Value(sceneName, mAl).Move(), mAl); - - Value scenes; - scenes.SetObject(); - { - Value scene; - scene.SetObject(); - { - Value nodes; - nodes.SetArray(); - - if (!mRootNodeId.empty()) { - nodes.PushBack(StringRef(mRootNodeId), mAl); - } - - scene.AddMember("nodes", nodes, mAl); - } - scenes.AddMember(Value(sceneName, mAl).Move(), scene, mAl); - } - mDoc.AddMember("scenes", scenes, mAl); - } - - std::string FindID(const aiString& str, const char* suffix) - { - std::string id = str.C_Str(); - - IdMap::iterator it; - - do { - if (!id.empty()) { - it = mUsedIds.find(id); - if (it == mUsedIds.end()) break; - - id += "-"; - } - - id += suffix; - - it = mUsedIds.find(id); - if (it == mUsedIds.end()) break; - - char buffer[256]; - int offset = sprintf(buffer, "%s-", id.c_str()); - for (int i = 0; it == mUsedIds.end(); ++i) { - ASSIMP_itoa10(buffer + offset, sizeof(buffer), i); - - id = buffer; - it = mUsedIds.find(id); - } - } while (false); // fake loop to allow using "break" - - mUsedIds[id] = true; - return id; - } -}; - - - glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties, bool isBinary) : mFilename(filename) , mIOSystem(pIOSystem) , mScene(pScene) , mProperties(pProperties) - , mIsBinary(isBinary) { - boost::scoped_ptr outfile(pIOSystem->Open(mFilename, "wt")); - if (outfile == 0) { - throw DeadlyExportError("Could not open output file: " + std::string(mFilename)); - } + boost::scoped_ptr asset(new glTF::Asset(pIOSystem)); + mAsset = asset.get(); if (isBinary) { - // we will write the header later, skip its size - outfile->Seek(sizeof(GLB_Header), aiOrigin_SET); + asset->SetAsBinary(); } + ExportMetadata(); - Document doc; - StringBuffer docBuffer; - { - glTFSceneExporter exportScene(doc, mScene); + //for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {} - bool pretty = true; - if (!isBinary && pretty) { - PrettyWriter writer(docBuffer); - doc.Accept(writer); - } - else { - Writer writer(docBuffer); - doc.Accept(writer); - } + //for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {} + + //for (unsigned int i = 0; i < pScene->mNumLights; ++i) {} + + + ExportMaterials(); + + ExportMeshes(); + + //for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {} + + + if (mScene->mRootNode) { + ExportNode(mScene->mRootNode); } - if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { - throw DeadlyExportError("Failed to write scene data!"); - } + ExportScene(); - if (isBinary) { - WriteBinaryData(outfile.get(), docBuffer.GetSize()); - } + + glTF::AssetWriter writer(*mAsset); + writer.WriteFile(filename); } -void glTFExporter::WriteBinaryData(IOStream* outfile, std::size_t sceneLength) +static void CopyValue(const aiMatrix4x4& v, glTF::mat4& o) +{ + o[ 0] = v.a1; o[ 1] = v.b1; o[ 2] = v.c1; o[ 3] = v.d1; + o[ 4] = v.a2; o[ 5] = v.b2; o[ 6] = v.c2; o[ 7] = v.d2; + o[ 8] = v.a3; o[ 9] = v.b3; o[10] = v.c3; o[11] = v.d3; + o[12] = v.a4; o[13] = v.b4; o[14] = v.c4; o[15] = v.d4; +} + +inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, + unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) { - // - // write the body data - // + if (!count || !data) return Ref(); - if (!mBodyData.empty()) { - std::size_t bodyOffset = sizeof(GLB_Header) + sceneLength; - bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4 + unsigned int numCompsIn = AttribType::GetNumComponents(typeIn); + unsigned int numCompsOut = AttribType::GetNumComponents(typeOut); + unsigned int bytesPerComp = ComponentTypeSize(compType); - outfile->Seek(bodyOffset, aiOrigin_SET); + size_t offset = buffer->byteLength; + size_t length = count * numCompsOut * bytesPerComp; + buffer->Grow(length); - if (outfile->Write(&mBodyData[0], mBodyData.size(), 1) != 1) { - throw DeadlyExportError("Failed to write body data!"); + // bufferView + Ref bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view")); + bv->buffer = buffer; + bv->byteOffset = 0; + bv->byteLength = length; //! The target that the WebGL buffer should be bound to. + bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER; + + // accessor + Ref acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor")); + acc->bufferView = bv; + acc->byteOffset = offset; + acc->byteStride = 0; + acc->componentType = compType; + acc->count = count; + acc->type = typeOut; + + // copy the data + acc->WriteData(count, data, numCompsIn*bytesPerComp); + + return acc; +} + +namespace { + void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) { + if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {} + } +} + +void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt) +{ + aiString tex; + aiColor4D col; + if (mat->GetTextureCount(tt) > 0) { + if (mat->Get(AI_MATKEY_TEXTURE(tt, 0), tex) == AI_SUCCESS) { + std::string path = tex.C_Str(); + + if (path.size() > 0) { + if (path[0] != '*') { + std::map::iterator it = mTexturesByPath.find(path); + if (it != mTexturesByPath.end()) { + prop.texture = mAsset->textures.Get(it->second); + } + } + + if (!prop.texture) { + std::string texId = mAsset->FindUniqueID("", "texture"); + prop.texture = mAsset->textures.Create(texId); + mTexturesByPath[path] = prop.texture.GetIndex(); + + std::string imgId = mAsset->FindUniqueID("", "image"); + prop.texture->source = mAsset->images.Create(imgId); + + if (path[0] == '*') { // embedded + aiTexture* tex = mScene->mTextures[atoi(&path[1])]; + + uint8_t* data = reinterpret_cast(tex->pcData); + prop.texture->source->SetData(data, tex->mWidth, *mAsset); + + if (tex->achFormatHint[0]) { + std::string mimeType = "image/"; + mimeType += (memcmp(tex->achFormatHint, "jpg", 3) == 0) ? "jpeg" : tex->achFormatHint; + prop.texture->source->mimeType = mimeType; + } + } + else { + prop.texture->source->uri = path; + } + } + } } } - - // - // write the header - // - - outfile->Seek(0, aiOrigin_SET); - - GLB_Header header; - memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)); - - header.version = 1; - AI_SWAP4(header.version); - - header.length = sizeof(header) + sceneLength + mBodyData.size(); - AI_SWAP4(header.length); - - header.sceneLength = sceneLength; - AI_SWAP4(header.sceneLength); - - header.sceneFormat = SceneFormat_JSON; - AI_SWAP4(header.sceneFormat); - - if (outfile->Write(&header, sizeof(header), 1) != 1) { - throw DeadlyExportError("Failed to write the header!"); + if (mat->Get(propName, type, idx, col) == AI_SUCCESS) { + prop.color[0] = col.r; prop.color[1] = col.g; prop.color[2] = col.b; prop.color[3] = col.a; } } +void glTFExporter::ExportMaterials() +{ + aiString aiName; + for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { + const aiMaterial* mat = mScene->mMaterials[i]; + + + std::string name; + if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { + name = aiName.C_Str(); + } + name = mAsset->FindUniqueID(name, "material"); + + Ref m = mAsset->materials.Create(name); + + GetMatColorOrTex(mat, m->ambient, AI_MATKEY_COLOR_AMBIENT, aiTextureType_AMBIENT); + GetMatColorOrTex(mat, m->diffuse, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_DIFFUSE); + GetMatColorOrTex(mat, m->specular, AI_MATKEY_COLOR_SPECULAR, aiTextureType_SPECULAR); + GetMatColorOrTex(mat, m->emission, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_EMISSIVE); + + GetMatScalar(mat, m->shininess, AI_MATKEY_SHININESS); + } +} + +void glTFExporter::ExportMeshes() +{ + for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) { + const aiMesh* aim = mScene->mMeshes[i]; + + std::string meshId = mAsset->FindUniqueID(aim->mName.C_Str(), "mesh"); + Ref m = mAsset->meshes.Create(meshId); + m->primitives.resize(1); + Mesh::Primitive& p = m->primitives.back(); + + p.material = mAsset->materials.Get(aim->mMaterialIndex); + + std::string bufferId = mAsset->FindUniqueID(meshId, "buffer"); + + Ref b = mAsset->GetBodyBuffer(); + if (!b) { + b = mAsset->buffers.Create(bufferId); + } + + Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + if (v) p.attributes.position.push_back(v); + + Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + if (n) p.attributes.normal.push_back(n); + + for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (aim->mNumUVComponents[i] > 0) { + AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; + Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, true); + if (tc) p.attributes.texcoord.push_back(tc); + } + } + + if (aim->mNumFaces > 0) { + unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices; + std::vector indices; + indices.resize(aim->mNumFaces * nIndicesPerFace); + for (size_t i = 0; i < aim->mNumFaces; ++i) { + for (size_t j = 0; j < nIndicesPerFace; ++j) { + indices[i*nIndicesPerFace + j] = uint16_t(aim->mFaces[i].mIndices[j]); + } + } + p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT); + } + + switch (aim->mPrimitiveTypes) { + case aiPrimitiveType_POLYGON: + p.mode = PrimitiveMode_TRIANGLES; break; // TODO implement this + case aiPrimitiveType_LINE: + p.mode = PrimitiveMode_LINES; break; + case aiPrimitiveType_POINT: + p.mode = PrimitiveMode_POINTS; break; + default: // aiPrimitiveType_TRIANGLE + p.mode = PrimitiveMode_TRIANGLES; + } + } +} + +size_t glTFExporter::ExportNode(const aiNode* n) +{ + Ref node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node")); + + if (!n->mTransformation.IsIdentity()) { + node->matrix.isPresent = true; + CopyValue(n->mTransformation, node->matrix.value); + } + + for (unsigned int i = 0; i < n->mNumMeshes; ++i) { + node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); + } + + for (unsigned int i = 0; i < n->mNumChildren; ++i) { + size_t idx = ExportNode(n->mChildren[i]); + node->children.push_back(mAsset->nodes.Get(idx)); + } + + return node.GetIndex(); +} + + +void glTFExporter::ExportScene() +{ + const char* sceneName = "defaultScene"; + Ref scene = mAsset->scenes.Create(sceneName); + + // root node will be the first one exported (idx 0) + if (mAsset->nodes.Size() > 0) { + scene->nodes.push_back(mAsset->nodes.Get(0u)); + } + + // set as the default scene + mAsset->scene = scene; +} + +void glTFExporter::ExportMetadata() +{ + glTF::AssetMetadata& asset = mAsset->asset; + asset.version = 1; + + char buffer[256]; + sprintf(buffer, "Open Asset Import Library (assimp v%d.%d.%d)", + aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision()); + + asset.generator = buffer; +} + + + + diff --git a/code/glTFExporter.h b/code/glTFExporter.h index 39dbf04d6..4b916cc83 100644 --- a/code/glTFExporter.h +++ b/code/glTFExporter.h @@ -45,11 +45,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_GLTFEXPORTER_H_INC #include +#include #include #include #include +#include "boost/scoped_ptr.hpp" + + struct aiScene; +struct aiNode; +struct aiMaterial; + +namespace glTF +{ + class Asset; + + struct TexProperty; +} namespace Assimp { @@ -57,7 +70,6 @@ namespace Assimp class IOStream; class ExportProperties; - // ------------------------------------------------------------------------------------------------ /** Helper class to export a given scene to an glTF file. */ // ------------------------------------------------------------------------------------------------ @@ -74,12 +86,21 @@ namespace Assimp IOSystem* mIOSystem; const aiScene* mScene; const ExportProperties* mProperties; - bool mIsBinary; + + std::map mTexturesByPath; + + glTF::Asset* mAsset; std::vector mBodyData; void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); + void GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt); + void ExportMetadata(); + void ExportMaterials(); + void ExportMeshes(); + size_t ExportNode(const aiNode* node); + void ExportScene(); }; } diff --git a/code/glTFFileData.h b/code/glTFFileData.h deleted file mode 100644 index 2a124d377..000000000 --- a/code/glTFFileData.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp team -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#ifndef AI_GLTFFILEDATA_H_INC -#define AI_GLTFFILEDATA_H_INC - -#include - -namespace Assimp { -namespace glTF { - - -//! Magic number for GLB files -#define AI_GLB_MAGIC_NUMBER "glTF" - - -#include "./../include/assimp/Compiler/pushpack1.h" - -// KHR_binary_glTF (binary .glb file) -// 20-byte header (+ the JSON + a "body" data section) -struct GLB_Header -{ - //! Magic number: "glTF" - unsigned char magic[4]; // "glTF" - - //! Version number (always 1 as of the last update) - uint32_t version; - - //! Total length of the Binary glTF, including header, scene, and body, in bytes - uint32_t length; - - //! Length, in bytes, of the glTF scene - uint32_t sceneLength; - - //! Specifies the format of the glTF scene (see the SceneFormat enum) - uint32_t sceneFormat; -} PACK_STRUCT; - -#include "./../include/assimp/Compiler/poppack1.h" - - - -//! Values for the GLB_Header::sceneFormat field -enum SceneFormat -{ - SceneFormat_JSON = 0 -}; - - -//! Values for the mesh primitive modes -enum PrimitiveMode -{ - PrimitiveMode_POINTS = 0, - PrimitiveMode_LINES = 1, - PrimitiveMode_LINE_LOOP = 2, - PrimitiveMode_LINE_STRIP = 3, - PrimitiveMode_TRIANGLES = 4, - PrimitiveMode_TRIANGLE_STRIP = 5, - PrimitiveMode_TRIANGLE_FAN = 6 -}; - - -//! Values for the accessors component type field -enum ComponentType -{ - ComponentType_BYTE = 5120, - ComponentType_UNSIGNED_BYTE = 5121, - ComponentType_SHORT = 5122, - ComponentType_UNSIGNED_SHORT = 5123, - ComponentType_FLOAT = 5126 -}; - - -//! Will hold the enabled extensions -struct Extensions -{ - bool KHR_binary_glTF; -}; - - -} // end namespaces -} - - -#endif // AI_GLTFFILEDATA_H_INC - diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 2df1ea458..d62271845 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -41,1059 +41,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER #include "glTFImporter.h" -#include "StreamReader.h" -#include "DefaultIOSystem.h" -#include +#include "StringComparison.h" + +#include "boost/scoped_ptr.hpp" #include #include #include #include +#include -#include "glTFFileData.h" -#include "glTFUtil.h" - -#define RAPIDJSON_HAS_STDSTRING 1 -#include -#include -#include - -using namespace rapidjson; +#include "glTFAsset.h" using namespace Assimp; -using namespace Assimp::glTF; - - -using boost::shared_ptr; -using boost::scoped_ptr; - -// (cannot typedef' templated classes, and "using" is c++11) -#define Ptr shared_ptr - -// (used everywhere, and cannot use "auto") -typedef rapidjson::Value::MemberIterator MemIt; +using namespace glTF; // -// JSON Value reading helpers +// glTFImporter // - -#define GETF(VAL, OUT) { if ((VAL).IsNumber()) (OUT) = static_cast((VAL).GetDouble()); } - -template -struct ReadHelper { }; - -template<> struct ReadHelper { static bool Read(Value& val, int& out) { - return val.IsInt() ? val.GetInt(), true : false; -}}; - -template<> struct ReadHelper { static bool Read(Value& val, unsigned int& out) { - return val.IsInt() ? out = static_cast(val.GetInt()), true : false; -}}; - -template<> struct ReadHelper { static bool Read(Value& val, float& out) { - return val.IsNumber() ? out = static_cast(val.GetDouble()), true : false; -}}; - -template<> struct ReadHelper { static bool Read(Value& val, const char*& out) { - return val.IsString() ? out = val.GetString(), true : false; -}}; - -template<> struct ReadHelper { static bool Read(Value& val, std::string& out) { - return val.IsString() ? out = val.GetString(), true : false; -}}; - -template<> struct ReadHelper { static bool Read(Value& v, aiColor3D& out) { - if (!v.IsArray() || v.Size() < 3) return false; - GETF(v[0], out.r); GETF(v[1], out.g); GETF(v[2], out.b); - return true; -}}; - -template<> struct ReadHelper { static bool Read(Value& v, aiVector3D& out) { - if (!v.IsArray() || v.Size() != 3) return false; - GETF(v[0], out.x); GETF(v[1], out.y); GETF(v[2], out.z); - return true; -}}; - -template<> struct ReadHelper { static bool Read(Value& v, aiQuaternion& out) { - if (!v.IsArray() || v.Size() != 4) return false; - GETF(v[0], out.x); GETF(v[1], out.y); GETF(v[2], out.z); GETF(v[3], out.w); - return true; -}}; - -template<> struct ReadHelper { static bool Read(Value& v, aiMatrix4x4& o) { - if (!v.IsArray() || v.Size() != 16) return false; - GETF(v[ 0], o.a1); GETF(v[ 1], o.b1); GETF(v[ 2], o.c1); GETF(v[ 3], o.d1); - GETF(v[ 4], o.a2); GETF(v[ 5], o.b2); GETF(v[ 6], o.c2); GETF(v[ 7], o.d2); - GETF(v[ 8], o.a3); GETF(v[ 9], o.b3); GETF(v[10], o.c3); GETF(v[11], o.d3); - GETF(v[12], o.a4); GETF(v[13], o.b4); GETF(v[14], o.c4); GETF(v[15], o.d4); - return true; -}}; - -template -inline static bool Read(Value& val, T& out) -{ - return ReadHelper::Read(val, out); -} - -template -inline static bool ReadMember(Value& obj, const char* id, T& out) -{ - MemIt it = obj.FindMember(id); - if (it != obj.MemberEnd()) { - return ReadHelper::Read(it->value, out); - } - return false; -} - -template -inline static T TryReadMember(Value& obj, const char* id, T defaultValue) -{ - T out; - return ReadMember(obj, id, out) ? out : defaultValue; -} - - -//! References a sequence of loaded elements (e.g. meshes) -typedef std::pair Range; - - - -// -// glTFReader class -// - -//! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID -template< class T, class INST, T(INST::*FACTORY_FN)(const char*, Value&)> -class LazyDict -{ - typedef typename std::gltf_unordered_map Map; - - Value* mDict; //! JSON dictionary object - const char* mDictId; //! ID of the dictionary object - INST& mInstance; //! The reader object instance - Map mReadObjs; //! The read objects - -public: - LazyDict(INST& instance, const char* dictId) - : mDictId(dictId), mInstance(instance) - { - Document& doc = mInstance.GetDocument(); - - MemIt it = doc.FindMember(dictId); - mDict = (it != doc.MemberEnd() && it->value.IsObject()) ? &it->value : 0; - } - - T Get(const char* id) - { - if (!mDict) return T(); // section was missing - - typename Map::iterator it = mReadObjs.find(id); - if (it != mReadObjs.end()) { // already created? - return it->second; - } - - // read it from the JSON object - MemIt obj = mDict->FindMember(id); - if (obj == mDict->MemberEnd()) { - throw DeadlyImportError("Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\""); - } - - // create an instance of the given type - T val = (mInstance.*FACTORY_FN)(id, obj->value); - mReadObjs[id] = val; - return val; - } -}; - -struct Buffer; -struct BufferView; -struct Accessor; - -struct Image; -struct Texture; - -//! Handles the reading of the glTF JSON document -class glTFReader -{ - aiScene* mScene; - Document& mDoc; - IOSystem& mIO; - - // Vectors of imported objects, will be copied to mScene - std::vector mImpMaterials; - std::vector mImpMeshes; - std::vector mImpTextures; - - Extensions mExtensions; - - Ptr mBodyBuffer; //! Special buffer containing the body data - - - Ptr LoadBuffer(const char* id, Value& obj); - Ptr LoadBufferView(const char* id, Value& obj); - Ptr LoadAccessor(const char* id, Value& obj); - - Ptr LoadImage(const char* id, Value& obj); - Ptr LoadTexture(const char* id, Value& obj); - - aiNode* LoadNode(const char* id, Value& node); - Range LoadMesh(const char* id, Value& mesh); - unsigned int LoadMaterial(const char* id, Value& material); - - typedef glTFReader T; // (to shorten next declarations) - - LazyDict, T, &T::LoadAccessor> mAccessors; - //LazyDict mAnimations; - //LazyDict mAssets; - LazyDict, T, &T::LoadBuffer> mBuffers; - LazyDict, T, &T::LoadBufferView> mBufferViews; - //LazyDict mCameras; - LazyDict, T, &T::LoadImage> mImages; - LazyDict mMaterials; - LazyDict mMeshes; - LazyDict mNodes; - //LazyDict, T, &T::LoadProgram> mPrograms; - //LazyDict, T, &T::LoadSampler> mSamplers; - //LazyDict, T, &T::LoadShader> mShaders; - //LazyDict, T, &T::LoadSkin> mSkins; - //LazyDict,T, &T::LoadTechnique> mTechniques; - LazyDict, T, &T::LoadTexture> mTextures; - - - void LoadScene(Value& scene) - { - MemIt nodesm = scene.FindMember("nodes"); - if (nodesm != scene.MemberEnd() && nodesm->value.IsArray()) { - Value& nodes = nodesm->value; - - unsigned int numRootNodes = nodes.Size(); - if (numRootNodes == 1) { // a single root node: use it - if (nodes[0].IsString()) { - mScene->mRootNode = mNodes.Get(nodes[0].GetString()); - } - } - else if (numRootNodes > 1) { // more than one root node: create a fake root - aiNode* root = new aiNode("ROOT"); - root->mChildren = new aiNode*[numRootNodes]; - for (unsigned int i = 0; i < numRootNodes; ++i) { - if (nodes[i].IsString()) { - aiNode* node = mNodes.Get(nodes[i].GetString()); - if (node) { - node->mParent = root; - root->mChildren[root->mNumChildren++] = node; - } - } - } - mScene->mRootNode = root; - } - } - - //if (!mScene->mRootNode) { - //mScene->mRootNode = new aiNode("EMPTY"); - //} - } - - void SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType, - const char* pKey, unsigned int type, unsigned int idx); - - void CopyData() - { - // TODO: it does not split the loaded vertices, should it? - mScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; - - if (mImpMaterials.empty()) { - mImpMaterials.push_back(new aiMaterial()); - } - - if (mImpMaterials.size()) { - mScene->mNumMaterials = mImpMaterials.size(); - mScene->mMaterials = new aiMaterial*[mImpMaterials.size()]; - std::swap_ranges(mImpMaterials.begin(), mImpMaterials.end(), mScene->mMaterials); - } - - if (mImpMeshes.size()) { - mScene->mNumMeshes = mImpMeshes.size(); - mScene->mMeshes = new aiMesh*[mImpMeshes.size()]; - std::swap_ranges(mImpMeshes.begin(), mImpMeshes.end(), mScene->mMeshes); - } - - if (mImpTextures.size()) { - mScene->mNumTextures = mImpTextures.size(); - mScene->mTextures = new aiTexture*[mImpTextures.size()]; - std::swap_ranges(mImpTextures.begin(), mImpTextures.end(), mScene->mTextures); - } - } - -public: - glTFReader(aiScene* scene, Document& document, IOSystem& iohandler, shared_ptr& bodyBuff) : - mScene(scene), - mDoc(document), - mIO(iohandler), - mBodyBuffer(bodyBuff), - mAccessors(*this, "accessors"), - //mAnimations(*this, "animations"), - //mAssets(*this, "assets"), - mBuffers(*this, "buffers"), - mBufferViews(*this, "bufferViews"), - //mCameras(*this, "cameras"), - mImages(*this, "images"), - mMaterials(*this, "materials"), - mMeshes(*this, "meshes"), - mNodes(*this, "nodes"), - //mPrograms(*this, "programs"), - //mSamplers(*this, "samplers"), - //mShaders(*this, "shaders"), - //mSkins(*this, "skins"), - //mTechniques(*this, "techniques"), - mTextures(*this, "textures") - { - memset(&mExtensions, 0, sizeof(mExtensions)); - } - - Document& GetDocument() - { - return mDoc; - } - - //! Main function - void Load() - { - // read the used extensions - MemIt extensionsUsed = mDoc.FindMember("extensionsUsed"); - if (extensionsUsed != mDoc.MemberEnd() && extensionsUsed->value.IsArray()) { - std::gltf_unordered_map exts; - - for (unsigned int i = 0; i < extensionsUsed->value.Size(); ++i) { - if (extensionsUsed->value[i].IsString()) { - exts[extensionsUsed->value[i].GetString()] = true; - } - } - - if (exts.find("KHR_binary_glTF") != exts.end()) { - mExtensions.KHR_binary_glTF = true; - } - } - - - const char* sceneId = 0; - - // the "scene" property specifies which scene to load - { - MemIt scene = mDoc.FindMember("scene"); - if (scene != mDoc.MemberEnd() && scene->value.IsString()) { - sceneId = scene->value.GetString(); - } - } - - MemIt scene; - - MemIt scenes = mDoc.FindMember("scenes"); - if (scenes != mDoc.MemberEnd() && scenes->value.IsObject()) { - if (sceneId) { - scene = scenes->value.FindMember(sceneId); - if (scene == scenes->value.MemberEnd()) { - //ThrowException("Missing scene!"); - } - } - else { // if not specified, use the first one - scene = scenes->value.MemberBegin(); - } - } - - if (scene != scenes->value.MemberEnd()) { - LoadScene(scene->value); - } - - CopyData(); - } -}; - -struct Buffer -{ -private: - std::size_t byteLength; - shared_ptr data; - -public: - Buffer(shared_ptr& d, std::size_t length) - : data(d), byteLength(length) - { } - - std::size_t GetLength() const - { - return byteLength; - } - - uint8_t* GetPointer() - { - return data.get(); - } - - static Buffer* FromStream(IOStream& stream, std::size_t length = 0, std::size_t baseOffset = 0) - { - if (!length) { - length = stream.FileSize(); - } - - if (baseOffset) { - stream.Seek(baseOffset, aiOrigin_SET); - } - - shared_ptr data(new uint8_t[length]); - - - if (stream.Read(data.get(), length, 1) != 1) { - throw DeadlyImportError("Unable to load buffer from file!"); - } - - return new Buffer(data, length); - } -}; - - -Ptr glTFReader::LoadBuffer(const char* id, Value& obj) -{ - if (!obj.IsObject()) return Ptr(); - - if (mExtensions.KHR_binary_glTF && strcmp(id, "KHR_binary_glTF") == 0) { - return mBodyBuffer; - } - else { - const char* uri = TryReadMember(obj, "uri", 0); - - Buffer* b = 0; - if (IsDataURI(uri)) { - const char* comma = strchr(uri, ','); - *const_cast(comma) = '\0'; - - bool isBase64 = (strstr(uri, "base64") != 0); - if (isBase64) { - uint8_t* data; - std::size_t dataLen = DecodeBase64(comma + 1, data); - shared_ptr dataptr(data); - b = new Buffer(dataptr, dataLen); - } - } - else if (uri) { // Local file - unsigned int byteLength = TryReadMember(obj, "byteLength", 0u); - - scoped_ptr file(mIO.Open(uri)); - b = Buffer::FromStream(*file.get(), byteLength); - } - return Ptr(b); - } -} - - -struct BufferView -{ - Ptr buffer; - unsigned int byteOffset; - unsigned int byteLength; - - BufferView() {} - - BufferView(Value& obj) - { - Read(obj); - } - - void Read(Value& obj) - { - if (!obj.IsObject()) return; - - } - -}; - -Ptr glTFReader::LoadBufferView(const char* id, Value& obj) -{ - if (!obj.IsObject()) return Ptr(); - - - const char* bufferId = TryReadMember(obj, "buffer", 0); - if (!bufferId) return Ptr(); - - BufferView* bv = new BufferView(); - - bv->buffer = mBuffers.Get(bufferId); - bv->byteOffset = TryReadMember(obj, "byteOffset", 0u); - bv->byteLength = TryReadMember(obj, "byteLength", 0u); - - return Ptr(bv); -} - - -struct Accessor -{ - Ptr bufferView; - unsigned int byteOffset; - unsigned int byteStride; - ComponentType componentType; - unsigned int count; - std::string type; // "SCALAR", "VEC2", "VEC3", "VEC4", "MAT2", "MAT3", "MAT4" - //unsigned int max; - ///unsigned int min; - - unsigned int numComponents; - unsigned int bytesPerComponent; - unsigned int elemSize; - - uint8_t* data; - - inline uint8_t* GetPointer() - { - if (!bufferView || !bufferView->buffer) return 0; - - std::size_t offset = byteOffset + bufferView->byteOffset; - return bufferView->buffer->GetPointer() + offset; - } - - template - void ExtractData(T*& outData, unsigned int* outCount = 0, unsigned int* outComponents = 0) - { - ai_assert(data); - - const std::size_t totalSize = elemSize * count; - - const std::size_t targetElemSize = sizeof(T); - ai_assert(elemSize <= targetElemSize); - - ai_assert(count*byteStride <= bufferView->byteLength); - - outData = new T[count]; - if (byteStride == elemSize && targetElemSize == elemSize) { - memcpy(outData, data, totalSize); - } - else { - for (std::size_t i = 0; i < count; ++i) { - memcpy(outData + i, data + i*byteStride, elemSize); - } - } - - if (outCount) *outCount = count; - if (outComponents) *outComponents = numComponents; - } - - //! Gets the i-th value as defined by the accessor - template - T GetValue(int i) - { - ai_assert(data); - ai_assert(i*byteStride < bufferView->byteLength); - T value = T(); - memcpy(&value, data + i*byteStride, elemSize); - //value >>= 8 * (sizeof(T) - elemSize); - return value; - } - - //! Gets the i-th value as defined by the accessor - unsigned int GetUInt(int i) - { - return GetValue(i); - } -}; - -Ptr glTFReader::LoadAccessor(const char* id, Value& obj) -{ - if (!obj.IsObject()) return Ptr(); - - Accessor* a = new Accessor(); - - const char* bufferViewId = TryReadMember(obj, "bufferView", 0); - if (bufferViewId) { - a->bufferView = mBufferViews.Get(bufferViewId); - } - - int compType = TryReadMember(obj, "componentType", unsigned(ComponentType_BYTE)); - - a->byteOffset = TryReadMember(obj, "byteOffset", 0u); - a->byteStride = TryReadMember(obj, "byteStride", 0u); - a->componentType = static_cast(compType); - a->count = TryReadMember(obj, "count", 0u); - a->type = TryReadMember(obj, "type", ""); - - a->numComponents = 1; // "SCALAR" - if (a->type == "VEC2") a->numComponents = 2; - else if (a->type == "VEC3") a->numComponents = 3; - else if (a->type == "VEC4") a->numComponents = 4; - else if (a->type == "MAT2") a->numComponents = 4; - else if (a->type == "MAT3") a->numComponents = 9; - else if (a->type == "MAT4") a->numComponents = 16; - - switch (a->componentType) { - case ComponentType_SHORT: - case ComponentType_UNSIGNED_SHORT: - a->bytesPerComponent = 2; - break; - - case ComponentType_FLOAT: - a->bytesPerComponent = 4; - break; - - //case Accessor::ComponentType_BYTE: - //case Accessor::ComponentType_UNSIGNED_BYTE: - default: - a->bytesPerComponent = 1; - } - - a->elemSize = a->numComponents * a->bytesPerComponent; - if (!a->byteStride) a->byteStride = a->elemSize; - - a->data = a->GetPointer(); - - return Ptr(a); -} - -static inline void setFace(aiFace& face, int a) -{ - face.mNumIndices = 1; - face.mIndices = new unsigned int[1]; - face.mIndices[0] = a; -} - -static inline void setFace(aiFace& face, int a, int b) -{ - face.mNumIndices = 2; - face.mIndices = new unsigned int[2]; - face.mIndices[0] = a; - face.mIndices[1] = b; -} - -static inline void setFace(aiFace& face, int a, int b, int c) -{ - face.mNumIndices = 3; - face.mIndices = new unsigned int[3]; - face.mIndices[0] = a; - face.mIndices[1] = b; - face.mIndices[2] = c; -} - -Range glTFReader::LoadMesh(const char* id, Value& mesh) -{ - Range range; - range.first = mImpMeshes.size(); - range.second = mImpMeshes.size(); - - MemIt primitives = mesh.FindMember("primitives"); - if (primitives != mesh.MemberEnd() && primitives->value.IsArray()) { - for (unsigned int i = 0; i < primitives->value.Size(); ++i) { - Value& primitive = primitives->value[i]; - - aiMesh* aimesh = new aiMesh(); - mImpMeshes.push_back(aimesh); - ++range.second; - - MemIt mode = primitive.FindMember("mode"); - if (mode != primitive.MemberEnd() && mode->value.IsInt()) { - switch (mode->value.GetInt()) { - case PrimitiveMode_POINTS: - aimesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - - case PrimitiveMode_LINES: - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: - aimesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - - case PrimitiveMode_TRIANGLES: - case PrimitiveMode_TRIANGLE_STRIP: - case PrimitiveMode_TRIANGLE_FAN: - aimesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - } - } - - MemIt attrs = primitive.FindMember("attributes"); - if (attrs != primitive.MemberEnd() && attrs->value.IsObject()) { - for (MemIt it = attrs->value.MemberBegin(); it != attrs->value.MemberEnd(); ++it) { - if (!it->value.IsString()) continue; - const char* attr = it->name.GetString(); - const char* accessorId = it->value.GetString(); - - Ptr accessor = mAccessors.Get(accessorId); - if (!accessor) continue; - - if (strcmp(attr, "POSITION") == 0) { - accessor->ExtractData(aimesh->mVertices, &aimesh->mNumVertices); - } - else if (strcmp(attr, "NORMAL") == 0) { - accessor->ExtractData(aimesh->mNormals); - } - else if (strncmp(attr, "TEXCOORD_", 9) == 0) { - int idx = attr[9] - '0'; - if (idx >= 0 && idx <= AI_MAX_NUMBER_OF_TEXTURECOORDS) { - accessor->ExtractData(aimesh->mTextureCoords[idx], 0, &aimesh->mNumUVComponents[idx]); - } - } - } - } - - MemIt indices = primitive.FindMember("indices"); - if (indices != primitive.MemberEnd() && indices->value.IsString()) { - Ptr acc = mAccessors.Get(indices->value.GetString()); - if (acc) { - aiFace* faces = 0; - std::size_t nFaces = 0; - - int primitiveMode = mode->value.GetInt(); - switch (primitiveMode) { - case PrimitiveMode_POINTS: { - nFaces = acc->count; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < acc->count; ++i) { - setFace(faces[i], acc->GetUInt(i)); - } - break; - } - - case PrimitiveMode_LINES: { - nFaces = acc->count / 2; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < acc->count; i += 2) { - setFace(faces[i / 2], acc->GetUInt(i), acc->GetUInt(i + 1)); - } - break; - } - - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: { - nFaces = acc->count - ((primitiveMode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - faces = new aiFace[nFaces]; - setFace(faces[0], acc->GetUInt(0), acc->GetUInt(1)); - for (unsigned int i = 2; i < acc->count; ++i) { - setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetUInt(i)); - } - if (primitiveMode == PrimitiveMode_LINE_LOOP) { // close the loop - setFace(faces[acc->count - 1], faces[acc->count - 2].mIndices[1], faces[0].mIndices[0]); - } - break; - } - - case PrimitiveMode_TRIANGLES: { - nFaces = acc->count / 3; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < acc->count; i += 3) { - setFace(faces[i / 3], acc->GetUInt(i), acc->GetUInt(i + 1), acc->GetUInt(i + 2)); - } - break; - } - case PrimitiveMode_TRIANGLE_STRIP: { - nFaces = acc->count - 2; - faces = new aiFace[nFaces]; - setFace(faces[0], acc->GetUInt(0), acc->GetUInt(1), acc->GetUInt(2)); - for (unsigned int i = 3; i < acc->count; ++i) { - setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetUInt(i)); - } - break; - } - case PrimitiveMode_TRIANGLE_FAN: - nFaces = acc->count - 2; - faces = new aiFace[nFaces]; - setFace(faces[0], acc->GetUInt(0), acc->GetUInt(1), acc->GetUInt(2)); - for (unsigned int i = 3; i < acc->count; ++i) { - setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetUInt(i)); - } - break; - } - - if (faces) { - aimesh->mFaces = faces; - aimesh->mNumFaces = nFaces; - } - } - } - - - MemIt material = primitive.FindMember("material"); - if (material != primitive.MemberEnd() && material->value.IsString()) { - aimesh->mMaterialIndex = mMaterials.Get(material->value.GetString()); - } - } - } - - return range; -} - - -struct Image -{ - aiString uri; -}; - -struct Texture -{ - Ptr source; -}; - -Ptr glTFReader::LoadImage(const char* id, Value& obj) -{ - - Image* img = new Image(); - - std::size_t embeddedDataLen = 0; - uint8_t* embeddedData = 0; - const char* mimeType = 0; - - // Check for extensions first (to detect binary embedded data) - MemIt extensions = obj.FindMember("extensions"); - if (extensions != obj.MemberEnd()) { - Value& exts = extensions->value; - - MemIt KHR_binary_glTF = exts.FindMember("KHR_binary_glTF"); - if (KHR_binary_glTF != exts.MemberEnd() && KHR_binary_glTF->value.IsObject()) { - - int width = TryReadMember(KHR_binary_glTF->value, "width", 0); - int height = TryReadMember(KHR_binary_glTF->value, "height", 0); - - ReadMember(KHR_binary_glTF->value, "mimeType", mimeType); - - const char* bufferViewId; - if (ReadMember(KHR_binary_glTF->value, "bufferView", bufferViewId)) { - Ptr bv = mBufferViews.Get(bufferViewId); - if (bv) { - embeddedDataLen = bv->byteLength; - embeddedData = new uint8_t[embeddedDataLen]; - memcpy(embeddedData, bv->buffer->GetPointer() + bv->byteOffset, embeddedDataLen); - } - } - } - } - - if (!embeddedDataLen) { - const char* uri; - if (ReadMember(obj, "uri", uri)) { - if (IsDataURI(uri)) { - const char* comma = strchr(uri, ','); - *const_cast(comma) = '\0'; - - bool isBase64 = (strstr(uri, "base64") != 0); - if (isBase64) { - embeddedDataLen = DecodeBase64(comma + 1, embeddedData); - } - - const char* sc = strchr(uri, ';'); - if (sc != 0) { - *const_cast(sc) = '\0'; - mimeType = uri; - } - } - else { - img->uri = uri; - } - } - } - - // Add the embedded texture - if (embeddedDataLen > 0) { - aiTexture* tex = new aiTexture(); - mImpTextures.push_back(tex); - - tex->mWidth = static_cast(embeddedDataLen); - tex->mHeight = 0; - tex->pcData = reinterpret_cast(embeddedData); - - if (mimeType) { - const char* ext = strchr(mimeType, '/') + 1; - if (ext) { - if (strcmp(ext, "jpeg") == 0) ext = "jpg"; - - std::size_t len = strlen(ext); - if (len <= 3) { - strcpy(tex->achFormatHint, ext); - } - } - } - - // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) - img->uri.data[0] = '*'; - img->uri.length = 1 + ASSIMP_itoa10(img->uri.data + 1, MAXLEN - 1, mImpTextures.size() - 1); - } - - return Ptr(img); -} - -Ptr glTFReader::LoadTexture(const char* id, Value& obj) -{ - Texture* tex = new Texture(); - - const char* source; - if (ReadMember(obj, "source", source)) { - tex->source = mImages.Get(source); - } - - return Ptr(tex); -} - -void glTFReader::SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) -{ - MemIt prop = vals.FindMember(propName); - if (prop != vals.MemberEnd()) { - aiColor3D col; - if (Read(prop->value, col)) { - mat->AddProperty(&col, 1, pKey, type, idx); - } - else if (prop->value.IsString()) { - Ptr tex = mTextures.Get(prop->value.GetString()); - if (tex && tex->source) { - mat->AddProperty(&tex->source->uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); - } - } - } -} - -unsigned int glTFReader::LoadMaterial(const char* id, Value& material) -{ - aiMaterial* mat = new aiMaterial(); - mImpMaterials.push_back(mat); - - const char* name; - if (ReadMember(material, "name", name)) { - aiString str(name); - mat->AddProperty(&str, AI_MATKEY_NAME); - } - - MemIt values = material.FindMember("values"); - if (values != material.MemberEnd() && values->value.IsObject()) { - Value& vals = values->value; - - SetMaterialColorProperty(mat, vals, "diffuse", aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); - SetMaterialColorProperty(mat, vals, "specular", aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - SetMaterialColorProperty(mat, vals, "ambient", aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); - - float shininess; - if (ReadMember(vals, "shininess", shininess)) { - mat->AddProperty(&shininess, 1, AI_MATKEY_SHININESS); - } - } - - MemIt extensions = material.FindMember("values"); - if (extensions != material.MemberEnd() && extensions->value.IsObject()) { - Value& exts = extensions->value; - - MemIt KHR_materials_common = exts.FindMember("KHR_materials_common"); - if (KHR_materials_common != exts.MemberEnd() && KHR_materials_common->value.IsObject()) { - // TODO: support KHR_materials_common (https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_common) - } - } - - return static_cast(mImpMaterials.size() - 1); -} - -aiNode* glTFReader::LoadNode(const char* id, Value& node) -{ - aiNode* ainode = new aiNode(id); - - //MemIt name = node.FindMember("name"); - //if (name != node.MemberEnd() && name->value.IsString()) { - // strcpy(ainode->mName.data, name->value.GetString()); - //} - - MemIt children = node.FindMember("children"); - if (children != node.MemberEnd() && children->value.IsArray()) { - - ainode->mChildren = new aiNode*[children->value.Size()]; - //ainode->mNumChildren = 0; - - for (unsigned int i = 0; i < children->value.Size(); ++i) { - Value& child = children->value[i]; - if (child.IsString()) { - // get/create the child node - aiNode* aichild = mNodes.Get(child.GetString()); - if (aichild) { - aichild->mParent = ainode; - ainode->mChildren[ainode->mNumChildren++] = aichild; - } - } - } - } - - aiMatrix4x4& transf = ainode->mTransformation; - - MemIt matrix = node.FindMember("matrix"); - if (matrix != node.MemberEnd()) { - Read(matrix->value, transf); - } - else { - MemIt translation = node.FindMember("translation"); - if (translation != node.MemberEnd()) { - aiVector3D trans; - if (Read(matrix->value, trans)) { - aiMatrix4x4 m; - aiMatrix4x4::Translation(trans, m); - transf = m * transf; - } - } - - MemIt scale = node.FindMember("scale"); - if (scale != node.MemberEnd()) { - aiVector3D scal(1.f); - if (Read(matrix->value, scal)) { - aiMatrix4x4 m; - aiMatrix4x4::Scaling(scal, m); - transf = m * transf; - } - } - - MemIt rotation = node.FindMember("rotation"); - if (rotation != node.MemberEnd()) { - aiQuaternion rot; - if (Read(matrix->value, rot)) { - transf = aiMatrix4x4(rot.GetMatrix()) * transf; - } - } - } - - MemIt meshes = node.FindMember("meshes"); - if (meshes != node.MemberEnd() && meshes->value.IsArray()) { - std::size_t numMeshes = (std::size_t)meshes->value.Size(); - - std::vector meshList; - - for (std::size_t i = 0; i < numMeshes; ++i) { - if (meshes->value[i].IsString()) { - Range range = mMeshes.Get(meshes->value[i].GetString()); - for (unsigned int m = range.first; m < range.second; ++m) { - meshList.push_back(m); - } - } - } - - if (meshList.size()) { - ainode->mNumMeshes = meshList.size(); - ainode->mMeshes = new unsigned int[meshList.size()]; - std::swap_ranges(meshList.begin(), meshList.end(), ainode->mMeshes); - } - } - - // TODO load "skeletons", "skin", "jointName", "camera" - - return ainode; -} - - - - - -// -// glTFImporter methods -// - -template<> const std::string LogFunctions::log_prefix = "glTF: "; - - - static const aiImporterDesc desc = { "glTF Importer", "", "", "", aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour - | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, 0, 0, 0, @@ -1107,106 +82,543 @@ glTFImporter::glTFImporter() } -glTFImporter::~glTFImporter() { +glTFImporter::~glTFImporter() +{ } -bool glTFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const { - const std::string& extension = GetExtension(pFile); - if (extension == "gltf" || extension == "glb") { - return true; - } - return false; -} - -const aiImporterDesc* glTFImporter::GetInfo() const { +const aiImporterDesc* glTFImporter::GetInfo() const +{ return &desc; } -void glTFImporter::ReadBinaryHeader(IOStream& stream) +bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { - GLB_Header header; - if (stream.Read(&header, sizeof(header), 1) != 1) { - ThrowException("Unable to read the file header"); + const std::string& extension = GetExtension(pFile); + + if (extension == "gltf" || extension == "glb") + return true; + + if ((checkSig || !extension.length()) && pIOHandler) { + char buffer[4]; + + boost::scoped_ptr pStream(pIOHandler->Open(pFile)); + if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) { + if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) { + return true; // Has GLB header + } + else if (memcmp(buffer, "{\r\n ", sizeof(buffer)) == 0 + || memcmp(buffer, "{\n ", sizeof(buffer)) == 0) { + // seems a JSON file, and we're the only format that can read them + return true; + } + } } - if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) { - ThrowException("Invalid binary glTF file"); - } - - AI_SWAP4(header.version); - if (header.version != 1) { - ThrowException("Unsupported binary glTF version"); - } - - AI_SWAP4(header.sceneFormat); - if (header.sceneFormat != SceneFormat_JSON) { - ThrowException("Unsupported binary glTF scene format"); - } - - AI_SWAP4(header.length); - AI_SWAP4(header.sceneLength); - - mSceneLength = static_cast(header.sceneLength); - - mBodyOffset = sizeof(header) + mSceneLength; - mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4 - - mBodyLength = header.length - mBodyOffset; + return false; } -void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) { - scoped_ptr stream(pIOHandler->Open(pFile, "rb")); - if (!stream) { - ThrowException("Could not open file for reading"); - } - // is binary? then read the header - if (GetExtension(pFile) == "glb") { - ReadBinaryHeader(*stream); + +static void CopyValue(const glTF::vec3& v, aiColor3D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; +} + +static void CopyValue(const glTF::vec4& v, aiColor4D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3]; +} + +static void CopyValue(const glTF::vec4& v, aiColor3D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; +} + +static void CopyValue(const glTF::vec3& v, aiVector3D& out) +{ + out.x = v[0]; out.y = v[1]; out.z = v[2]; +} + +static void CopyValue(const glTF::vec4& v, aiQuaternion& out) +{ + out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3]; +} + +static void CopyValue(const glTF::mat4& v, aiMatrix4x4& o) +{ + o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3]; + o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7]; + o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11]; + o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15]; +} + +inline void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& r, glTF::TexProperty prop, aiMaterial* mat, + aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) +{ + if (prop.texture) { + if (prop.texture->source) { + aiString uri(prop.texture->source->uri); + + int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; + 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); + } + + mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); + } } else { - mSceneLength = stream->FileSize(); - mBodyLength = 0; + aiColor4D col; + CopyValue(prop.color, col); + if (col.r != 1.f || col.g != 1.f || col.b != 1.f || col.a != 1.f) { + mat->AddProperty(&col, 1, pKey, type, idx); + } + } +} + +void glTFImporter::ImportMaterials(glTF::Asset& r) +{ + mScene->mNumMaterials = r.materials.Size(); + mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials]; + + for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { + aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial(); + + Material& mat = r.materials[i]; + + /*if (!mat.name.empty())*/ { + aiString str(mat.id /*mat.name*/); + aimat->AddProperty(&str, AI_MATKEY_NAME); + } + + SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + + if (mat.shininess > 0.f) { + aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS); + } } + if (mScene->mNumMaterials == 0) { + mScene->mNumMaterials = 1; + mScene->mMaterials = new aiMaterial*[1]; + mScene->mMaterials[0] = new aiMaterial(); + } +} - // read the scene data - scoped_ptr sceneData = new char[mSceneLength + 1]; - sceneData[mSceneLength] = '\0'; +inline void SetFace(aiFace& face, int a) +{ + face.mNumIndices = 1; + face.mIndices = new unsigned int[1]; + face.mIndices[0] = a; +} - if (stream->Read(sceneData, 1, mSceneLength) != mSceneLength) { - ThrowException("Could not read the file contents"); +inline void SetFace(aiFace& face, int a, int b) +{ + face.mNumIndices = 2; + face.mIndices = new unsigned int[2]; + face.mIndices[0] = a; + face.mIndices[1] = b; +} + +inline void SetFace(aiFace& face, int a, int b, int c) +{ + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + face.mIndices[0] = a; + face.mIndices[1] = b; + face.mIndices[2] = c; +} + +void glTFImporter::ImportMeshes(glTF::Asset& r) +{ + std::vector meshes; + + unsigned int k = 0; + + for (unsigned int m = 0; m < r.meshes.Size(); ++m) { + Mesh& mesh = r.meshes[m]; + + meshOffsets.push_back(k); + k += mesh.primitives.size(); + + for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { + Mesh::Primitive& prim = mesh.primitives[p]; + + aiMesh* aim = new aiMesh(); + meshes.push_back(aim); + + aim->mName = mesh.id; + if (mesh.primitives.size() > 1) { + size_t& len = aim->mName.length; + aim->mName.data[len] = '-'; + len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, MAXLEN - len - 1, p); + } + + switch (prim.mode) { + case PrimitiveMode_POINTS: + aim->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + + case PrimitiveMode_LINES: + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: + aim->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + + case PrimitiveMode_TRIANGLES: + case PrimitiveMode_TRIANGLE_STRIP: + case PrimitiveMode_TRIANGLE_FAN: + aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + } + + Mesh::Primitive::Attributes& attr = prim.attributes; + if (attr.position.size() > 0 && attr.position[0]) { + aim->mNumVertices = attr.position[0]->count; + attr.position[0]->ExtractData(aim->mVertices); + } + + if (attr.normal.size() > 0 && attr.normal[0]) { + attr.normal[0]->ExtractData(aim->mNormals); + } + + for (size_t tc = 0; tc < attr.texcoord.size() && tc <= AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { + attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); + aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); + } + + + if (prim.indices) { + aiFace* faces = 0; + size_t nFaces = 0; + + unsigned int count = prim.indices->count; + + Accessor::Indexer data = prim.indices->GetIndexer(); + + switch (prim.mode) { + case PrimitiveMode_POINTS: { + nFaces = count; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFace(faces[i], data.GetUInt(i)); + } + break; + } + + case PrimitiveMode_LINES: { + nFaces = count / 2; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); + } + break; + } + + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); + for (unsigned int i = 2; i < count; ++i) { + SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + } + break; + } + + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + + if (faces) { + aim->mFaces = faces; + aim->mNumFaces = nFaces; + } + } + + + if (prim.material) { + aim->mMaterialIndex = prim.material.GetIndex(); + } + } } + meshOffsets.push_back(k); + + CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); +} - // parse the JSON document +void glTFImporter::ImportCameras(glTF::Asset& r) +{ + if (!r.cameras.Size()) return; - Document doc; - doc.ParseInsitu(sceneData); + mScene->mNumCameras = r.cameras.Size(); + mScene->mCameras = new aiCamera*[r.cameras.Size()]; - if (doc.HasParseError()) { - char buffer[32]; - ASSIMP_itoa10(buffer, doc.GetErrorOffset()); - ThrowException(std::string("JSON parse error, offset ") + buffer + ": " - + GetParseError_En(doc.GetParseError())); + for (size_t i = 0; i < r.cameras.Size(); ++i) { + Camera& cam = r.cameras[i]; + + aiCamera* aicam = mScene->mCameras[i] = new aiCamera(); + + if (cam.type == Camera::Perspective) { + + aicam->mAspect = cam.perspective.aspectRatio; + aicam->mHorizontalFOV = cam.perspective.yfov * aicam->mAspect; + aicam->mClipPlaneFar = cam.perspective.zfar; + aicam->mClipPlaneNear = cam.perspective.znear; + } + else { + // assimp does not support orthographic cameras + } + } +} + +void glTFImporter::ImportLights(glTF::Asset& r) +{ + if (!r.lights.Size()) return; + + mScene->mNumLights = r.lights.Size(); + mScene->mLights = new aiLight*[r.lights.Size()]; + + for (size_t i = 0; i < r.lights.Size(); ++i) { + Light& l = r.lights[i]; + + aiLight* ail = mScene->mLights[i] = new aiLight(); + + switch (l.type) { + case Light::Type_directional: + ail->mType = aiLightSource_DIRECTIONAL; break; + + case Light::Type_point: + ail->mType = aiLightSource_POINT; break; + + case Light::Type_spot: + ail->mType = aiLightSource_SPOT; break; + + case Light::Type_ambient: + ail->mType = aiLightSource_AMBIENT; break; + } + + CopyValue(l.color, ail->mColorAmbient); + CopyValue(l.color, ail->mColorDiffuse); + CopyValue(l.color, ail->mColorSpecular); + + ail->mAngleOuterCone = l.falloffAngle; + ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all + + ail->mAttenuationConstant = l.constantAttenuation; + ail->mAttenuationLinear = l.linearAttenuation; + ail->mAttenuationQuadratic = l.quadraticAttenuation; + } +} + + +aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector& meshOffsets, glTF::Ref& ptr) +{ + Node& node = *ptr; + + aiNode* ainode = new aiNode(node.id); + + if (!node.children.empty()) { + ainode->mNumChildren = node.children.size(); + ainode->mChildren = new aiNode*[ainode->mNumChildren]; + + for (unsigned int i = 0; i < ainode->mNumChildren; ++i) { + aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]); + child->mParent = ainode; + ainode->mChildren[i] = child; + } } - if (!doc.IsObject()) { - ThrowException("gltf file must be a JSON object!"); + aiMatrix4x4 matrix = ainode->mTransformation; + if (node.matrix.isPresent) { + CopyValue(node.matrix.value, matrix); + } + else { + if (node.translation.isPresent) { + aiVector3D trans; + CopyValue(node.translation.value, trans); + aiMatrix4x4 t; + aiMatrix4x4::Translation(trans, t); + matrix = t * matrix; + } + + if (node.scale.isPresent) { + aiVector3D scal(1.f); + CopyValue(node.scale.value, scal); + aiMatrix4x4 s; + aiMatrix4x4::Scaling(scal, s); + matrix = s * matrix; + } + + + if (node.rotation.isPresent) { + aiQuaternion rot; + CopyValue(node.rotation.value, rot); + matrix = aiMatrix4x4(rot.GetMatrix()) * matrix; + } } + if (!node.meshes.empty()) { + int count = 0; + for (size_t i = 0; i < node.meshes.size(); ++i) { + int idx = node.meshes[i].GetIndex(); + count += meshOffsets[idx + 1] - meshOffsets[idx]; + } - // Buffer instance for the current file embedded contents - shared_ptr bodyBuffer; - if (mBodyLength > 0) { - bodyBuffer.reset(Buffer::FromStream(*stream, mBodyLength, mBodyOffset)); + ainode->mNumMeshes = count; + ainode->mMeshes = new unsigned int[count]; + + int k = 0; + for (size_t i = 0; i < node.meshes.size(); ++i) { + int idx = node.meshes[i].GetIndex(); + for (size_t j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) { + ainode->mMeshes[k] = j; + } + } } - // import the data - glTFReader reader(pScene, doc, *pIOHandler, bodyBuffer); - reader.Load(); + if (node.camera) { + pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName; + } + + if (node.light) { + pScene->mLights[node.light.GetIndex()]->mName = ainode->mName; + } + + return ainode; +} + +void glTFImporter::ImportNodes(glTF::Asset& r) +{ + if (!r.scene) return; + + std::vector< Ref > rootNodes = r.scene->nodes; + + // The root nodes + unsigned int numRootNodes = rootNodes.size(); + if (numRootNodes == 1) { // a single root node: use it + mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]); + } + else if (numRootNodes > 1) { // more than one root node: create a fake root + aiNode* root = new aiNode("ROOT"); + root->mChildren = new aiNode*[numRootNodes]; + for (unsigned int i = 0; i < numRootNodes; ++i) { + aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); + node->mParent = root; + root->mChildren[root->mNumChildren++] = node; + } + mScene->mRootNode = root; + } + + //if (!mScene->mRootNode) { + // mScene->mRootNode = new aiNode("EMPTY"); + //} +} + +void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) +{ + embeddedTexIdxs.resize(r.images.Size(), -1); + + int numEmbeddedTexs = 0; + for (size_t i = 0; i < r.images.Size(); ++i) { + if (r.images[i].HasData()) + numEmbeddedTexs += 1; + } + + if (numEmbeddedTexs == 0) + return; + + mScene->mTextures = new aiTexture*[numEmbeddedTexs]; + + // Add the embedded textures + for (size_t i = 0; i < r.images.Size(); ++i) { + Image img = r.images[i]; + if (!img.HasData()) continue; + + int idx = mScene->mNumTextures++; + embeddedTexIdxs[i] = idx; + + aiTexture* tex = mScene->mTextures[idx] = new aiTexture(); + + size_t length = img.GetDataLength(); + void* data = img.StealData(); + + tex->mWidth = static_cast(length); + tex->mHeight = 0; + tex->pcData = reinterpret_cast(data); + + if (!img.mimeType.empty()) { + const char* ext = strchr(img.mimeType.c_str(), '/') + 1; + if (ext) { + if (strcmp(ext, "jpeg") == 0) ext = "jpg"; + + size_t len = strlen(ext); + if (len <= 3) { + strcpy(tex->achFormatHint, ext); + } + } + } + } +} + +void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { + + this->mScene = pScene; + + // read the asset file + glTF::Asset asset(pIOHandler); + asset.Load(pFile, GetExtension(pFile) == "glb"); + + + // + // Copy the data out + // + + ImportEmbeddedTextures(asset); + ImportMaterials(asset); + + ImportMeshes(asset); + + ImportCameras(asset); + ImportLights(asset); + + ImportNodes(asset); + + // TODO: it does not split the loaded vertices, should it? + pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; if (pScene->mNumMeshes == 0) { pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; diff --git a/code/glTFImporter.h b/code/glTFImporter.h index 3de899915..b0b20c0b9 100644 --- a/code/glTFImporter.h +++ b/code/glTFImporter.h @@ -41,16 +41,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_GLTFIMPORTER_H_INC #include "BaseImporter.h" -#include "LogAux.h" #include "DefaultIOSystem.h" +struct aiNode; + + +namespace glTF +{ + class Asset; +} + namespace Assimp { /** * Load the glTF format. * https://github.com/KhronosGroup/glTF/tree/master/specification */ -class glTFImporter : public BaseImporter, public LogFunctions { +class glTFImporter : public BaseImporter{ public: glTFImporter(); virtual ~glTFImporter(); @@ -61,10 +68,20 @@ protected: virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ); private: - void ReadBinaryHeader(IOStream& stream); - std::size_t mSceneLength; - std::size_t mBodyOffset, mBodyLength; + std::vector meshOffsets; + + std::vector embeddedTexIdxs; + + aiScene* mScene; + + void ImportEmbeddedTextures(glTF::Asset& a); + void ImportMaterials(glTF::Asset& a); + void ImportMeshes(glTF::Asset& a); + void ImportCameras(glTF::Asset& a); + void ImportLights(glTF::Asset& a); + void ImportNodes(glTF::Asset& a); + }; } // Namespace assimp diff --git a/code/glTFUtil.cpp b/code/glTFUtil.cpp deleted file mode 100644 index 46ef32a42..000000000 --- a/code/glTFUtil.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp team -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#include "glTFUtil.h" - - -using namespace Assimp; -using namespace Assimp::glTF; - - -bool Assimp::glTF::IsDataURI(const char* uri) -{ - return strncmp(uri, "data:", 5) == 0; -} - - -static const uint8_t tableDecodeBase64[128] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, - 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, - 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, - 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static inline char EncodeCharBase64(uint8_t b) -{ - return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[b]; -} - -static inline uint8_t DecodeCharBase64(char c) -{ - return tableDecodeBase64[c]; // TODO faster with lookup table or ifs? - /*if (c >= 'A' && c <= 'Z') return c - 'A'; - if (c >= 'a' && c <= 'z') return c - 'a' + 26; - if (c >= '0' && c <= '9') return c - '0' + 52; - return c == '+' ? 62 : 63;*/ -} - -std::size_t Assimp::glTF::DecodeBase64( - const char* in, uint8_t*& out) -{ - return DecodeBase64(in, strlen(in), out); -} - -std::size_t Assimp::glTF::DecodeBase64( - const char* in, std::size_t inLength, uint8_t*& out) -{ - ai_assert(dataLen % 4 == 0); - - if (inLength < 4) { - out = 0; - return 0; - } - - int nEquals = int(in[inLength - 1] == '=') + - int(in[inLength - 2] == '='); - - std::size_t outLength = (inLength * 3) / 4 - nEquals; - out = new uint8_t[outLength]; - memset(out, 0, outLength); - - std::size_t j = 0; - - for (std::size_t i = 0; i < inLength; i += 4) { - uint8_t b0 = DecodeCharBase64(in[i]); - uint8_t b1 = DecodeCharBase64(in[i + 1]); - uint8_t b2 = DecodeCharBase64(in[i + 2]); - uint8_t b3 = DecodeCharBase64(in[i + 3]); - - out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4)); - out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2)); - out[j++] = (uint8_t)((b2 << 6) | b3); - } - - return outLength; -} - - - -void Assimp::glTF::EncodeBase64( - const uint8_t* in, std::size_t inLength, - std::string& out) -{ - std::size_t outLength = ((inLength + 2) / 3) * 4; - - out.resize(outLength); - - std::size_t j = 0; - for (std::size_t i = 0; i < inLength; i += 3) { - uint8_t b = (in[i] & 0xFC) >> 2; - out[j++] = EncodeCharBase64(b); - - b = (in[i] & 0x03) << 4; - if (i + 1 < inLength) { - b |= (in[i + 1] & 0xF0) >> 4; - out[j++] = EncodeCharBase64(b); - - b = (in[i + 1] & 0x0F) << 2; - if (i + 2 < inLength) { - b |= (in[i + 2] & 0xC0) >> 6; - out[j++] = EncodeCharBase64(b); - - b = in[i + 2] & 0x3F; - out[j++] = EncodeCharBase64(b); - } - else { - out[j++] = EncodeCharBase64(b); - out[j++] = '='; - } - } - else { - out[j++] = EncodeCharBase64(b); - out[j++] = '='; - out[j++] = '='; - } - } -} From d72443d6b071a2a4fab95f5d30fb14a0508a40cb Mon Sep 17 00:00:00 2001 From: Otger Date: Sun, 29 Nov 2015 20:17:06 +0100 Subject: [PATCH 67/77] Fixed gcc warnings and errors --- code/glTFAsset.h | 11 ++++- code/glTFAsset.inl | 33 ++++++++------- code/glTFAssetWriter.inl | 91 ++++++++++++++++++++-------------------- code/glTFExporter.cpp | 2 +- code/glTFImporter.cpp | 14 +++---- 5 files changed, 80 insertions(+), 71 deletions(-) diff --git a/code/glTFAsset.h b/code/glTFAsset.h index 4f6c37a3f..1511d28ea 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -353,6 +353,8 @@ namespace glTF //! Objects marked as special are not exported (used to emulate the binary body buffer) virtual bool IsSpecial() const { return false; } + + virtual ~Object() {} }; @@ -391,8 +393,8 @@ namespace glTF { friend struct Accessor; - uint8_t* data; Accessor& accessor; + uint8_t* data; size_t elemSize, stride; Indexer(Accessor& acc); @@ -535,6 +537,8 @@ namespace glTF std::string mimeType; + int width, height; + private: uint8_t* mData; size_t mDataLength; @@ -770,7 +774,10 @@ namespace glTF void AttachToDocument(Document& doc); void DetachFromDocument(); - void WriteObjects(AssetWriter& writer); + void WriteObjectsImpl(AssetWriter& writer); + + void WriteObjects(AssetWriter& writer) + { WriteObjectsImpl(writer); } Ref Add(T* obj); diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index 82f7a92f3..df5fa8721 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -61,7 +61,7 @@ namespace { template struct ReadHelper { static bool Read(Value& val, float (&out)[N]) { if (!val.IsArray() || val.Size() != N) return false; - for (int i = 0; i < N; ++i) { + for (size_t i = 0; i < N; ++i) { if (val[i].IsNumber()) out[i] = static_cast(val[i].GetDouble()); } @@ -446,7 +446,9 @@ T Accessor::Indexer::GetValue(int i) } inline Image::Image() - : mData(0) + : width(0) + , height(0) + , mData(0) , mDataLength(0) { @@ -459,8 +461,8 @@ inline void Image::Read(Value& obj, Asset& r) if (r.extensionsUsed.KHR_binary_glTF) { if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) { - int width = MemberOrDefault(*ext, "width", 0); - int height = MemberOrDefault(*ext, "height", 0); + width = MemberOrDefault(*ext, "width", 0); + height = MemberOrDefault(*ext, "height", 0); ReadMember(*ext, "mimeType", mimeType); @@ -607,25 +609,25 @@ namespace { inline bool GetAttribVector(Mesh::Primitive& p, const char* attr, Mesh::AccessorList*& v, int& pos) { - if (pos = Compare(attr, "POSITION")) { + if ((pos = Compare(attr, "POSITION"))) { v = &(p.attributes.position); } - else if (pos = Compare(attr, "NORMAL")) { + else if ((pos = Compare(attr, "NORMAL"))) { v = &(p.attributes.normal); } - else if (pos = Compare(attr, "TEXCOORD")) { + else if ((pos = Compare(attr, "TEXCOORD"))) { v = &(p.attributes.texcoord); } - else if (pos = Compare(attr, "COLOR")) { + else if ((pos = Compare(attr, "COLOR"))) { v = &(p.attributes.color); } - else if (pos = Compare(attr, "JOINT")) { + else if ((pos = Compare(attr, "JOINT"))) { v = &(p.attributes.joint); } - else if (pos = Compare(attr, "JOINTMATRIX")) { + else if ((pos = Compare(attr, "JOINTMATRIX"))) { v = &(p.attributes.jointmatrix); } - else if (pos = Compare(attr, "WEIGHT")) { + else if ((pos = Compare(attr, "WEIGHT"))) { v = &(p.attributes.weight); } else return false; @@ -647,7 +649,8 @@ inline void Mesh::Read(Value& obj, Asset& r) for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) { if (!it->value.IsString()) continue; const char* attr = it->name.GetString(); - // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. + // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, + // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. int undPos = 0; Mesh::AccessorList* vec = 0; @@ -920,7 +923,7 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) if (doc.HasParseError()) { char buffer[32]; - sprintf(buffer, "%u", doc.GetErrorOffset()); + sprintf(buffer, "%d", static_cast(doc.GetErrorOffset())); throw DeadlyImportError(std::string("JSON parse error, offset ") + buffer + ": " + GetParseError_En(doc.GetParseError())); } @@ -1107,12 +1110,12 @@ namespace Util inline char EncodeCharBase64(uint8_t b) { - return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[b]; + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)]; } inline uint8_t DecodeCharBase64(char c) { - return DATA::tableDecodeBase64[c]; // TODO faster with lookup table or ifs? + return DATA::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs? /*if (c >= 'A' && c <= 'Z') return c - 'A'; if (c >= 'a' && c <= 'z') return c - 'a' + 26; if (c >= '0' && c <= '9') return c - '0' + 52; diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index d6e313f93..174565ef3 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -190,7 +190,7 @@ namespace glTF { else { for (size_t i = 0; i < lst.size(); ++i) { char buffer[32]; - sprintf(buffer, "%s_%d", semantic, i); + sprintf(buffer, "%s_%d", semantic, int(i)); attrs.AddMember(Value(buffer, w.mAl).Move(), Value(lst[i]->id, w.mAl).Move(), w.mAl); } } @@ -304,52 +304,10 @@ namespace glTF { } - template - void LazyDict::WriteObjects(AssetWriter& w) - { - if (mObjs.empty()) return; - - Value* container = &w.mDoc; - - if (mExtId) { - Value* exts = FindObject(w.mDoc, "extensions"); - if (!exts) { - w.mDoc.AddMember("extensions", Value().SetObject().Move(), w.mDoc.GetAllocator()); - exts = FindObject(w.mDoc, "extensions"); - } - - if (!(container = FindObject(*exts, mExtId))) { - exts->AddMember(StringRef(mExtId), Value().SetObject().Move(), w.mDoc.GetAllocator()); - container = FindObject(*exts, mExtId); - } - } - - Value* dict; - if (!(dict = FindObject(*container, mDictId))) { - container->AddMember(StringRef(mDictId), Value().SetObject().Move(), w.mDoc.GetAllocator()); - dict = FindObject(*container, mDictId); - } - - for (size_t i = 0; i < mObjs.size(); ++i) { - if (mObjs[i]->IsSpecial()) continue; - - Value obj; - obj.SetObject(); - - if (!mObjs[i]->name.empty()) { - obj.AddMember("name", StringRef(mObjs[i]->name.c_str()), w.mAl); - } - - Write(obj, *mObjs[i], w); - - dict->AddMember(StringRef(mObjs[i]->id), obj, w.mAl); - } - } - AssetWriter::AssetWriter(Asset& a) - : mAsset(a) - , mDoc() + : mDoc() + , mAsset(a) , mAl(mDoc.GetAllocator()) { mDoc.SetObject(); @@ -368,7 +326,6 @@ namespace glTF { } } - void AssetWriter::WriteFile(const char* path) { bool isBinary = mAsset.extensionsUsed.KHR_binary_glTF; @@ -484,6 +441,48 @@ namespace glTF { mDoc.AddMember("extensionsUsed", exts, mAl); } + + template + void LazyDict::WriteObjectsImpl(AssetWriter& w) + { + if (mObjs.empty()) return; + + Value* container = &w.mDoc; + + if (mExtId) { + Value* exts = FindObject(w.mDoc, "extensions"); + if (!exts) { + w.mDoc.AddMember("extensions", Value().SetObject().Move(), w.mDoc.GetAllocator()); + exts = FindObject(w.mDoc, "extensions"); + } + + if (!(container = FindObject(*exts, mExtId))) { + exts->AddMember(StringRef(mExtId), Value().SetObject().Move(), w.mDoc.GetAllocator()); + container = FindObject(*exts, mExtId); + } + } + + Value* dict; + if (!(dict = FindObject(*container, mDictId))) { + container->AddMember(StringRef(mDictId), Value().SetObject().Move(), w.mDoc.GetAllocator()); + dict = FindObject(*container, mDictId); + } + + for (size_t i = 0; i < mObjs.size(); ++i) { + if (mObjs[i]->IsSpecial()) continue; + + Value obj; + obj.SetObject(); + + if (!mObjs[i]->name.empty()) { + obj.AddMember("name", StringRef(mObjs[i]->name.c_str()), w.mAl); + } + + Write(obj, *mObjs[i], w); + + dict->AddMember(StringRef(mObjs[i]->id), obj, w.mAl); + } + } } diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index b47e0da24..f11c51362 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -338,7 +338,7 @@ void glTFExporter::ExportScene() // root node will be the first one exported (idx 0) if (mAsset->nodes.Size() > 0) { - scene->nodes.push_back(mAsset->nodes.Get(0u)); + scene->nodes.push_back(mAsset->nodes.Get(size_t(0))); } // set as the default scene diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index d62271845..e8f8db96b 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -120,10 +120,10 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool -static void CopyValue(const glTF::vec3& v, aiColor3D& out) -{ - out.r = v[0]; out.g = v[1]; out.b = v[2]; -} +//static void CopyValue(const glTF::vec3& v, aiColor3D& out) +//{ +// out.r = v[0]; out.g = v[1]; out.b = v[2]; +//} static void CopyValue(const glTF::vec4& v, aiColor4D& out) { @@ -421,14 +421,14 @@ void glTFImporter::ImportLights(glTF::Asset& r) case Light::Type_directional: ail->mType = aiLightSource_DIRECTIONAL; break; - case Light::Type_point: - ail->mType = aiLightSource_POINT; break; - case Light::Type_spot: ail->mType = aiLightSource_SPOT; break; case Light::Type_ambient: ail->mType = aiLightSource_AMBIENT; break; + + default: // Light::Type_point + ail->mType = aiLightSource_POINT; break; } CopyValue(l.color, ail->mColorAmbient); From 714630cc1169982906448cd689d11f0a061d6adc Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 29 Nov 2015 20:37:05 +0100 Subject: [PATCH 68/77] Contrib: remove deprecated pacakgeContrib: remove deprecated pacakge.. --- contrib/picojson/.gitignore | 4 - contrib/picojson/.gitmodules | 0 contrib/picojson/.travis.yml | 8 - contrib/picojson/Changes | 25 - contrib/picojson/LICENSE | 25 - contrib/picojson/Makefile | 26 - contrib/picojson/README.mkdn | 195 ---- contrib/picojson/examples/github-issues.cc | 110 --- contrib/picojson/examples/iostream.cc | 70 -- contrib/picojson/examples/streaming.cc | 76 -- contrib/picojson/picojson.h | 1039 -------------------- contrib/picojson/picotest/picotest.c | 99 -- contrib/picojson/picotest/picotest.h | 39 - contrib/picojson/test.cc | 325 ------ 14 files changed, 2041 deletions(-) delete mode 100644 contrib/picojson/.gitignore delete mode 100644 contrib/picojson/.gitmodules delete mode 100644 contrib/picojson/.travis.yml delete mode 100644 contrib/picojson/Changes delete mode 100644 contrib/picojson/LICENSE delete mode 100644 contrib/picojson/Makefile delete mode 100644 contrib/picojson/README.mkdn delete mode 100644 contrib/picojson/examples/github-issues.cc delete mode 100644 contrib/picojson/examples/iostream.cc delete mode 100644 contrib/picojson/examples/streaming.cc delete mode 100644 contrib/picojson/picojson.h delete mode 100644 contrib/picojson/picotest/picotest.c delete mode 100644 contrib/picojson/picotest/picotest.h delete mode 100644 contrib/picojson/test.cc diff --git a/contrib/picojson/.gitignore b/contrib/picojson/.gitignore deleted file mode 100644 index 815b59fad..000000000 --- a/contrib/picojson/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*~ -a.out -test-core -test-core-int64 diff --git a/contrib/picojson/.gitmodules b/contrib/picojson/.gitmodules deleted file mode 100644 index e69de29bb..000000000 diff --git a/contrib/picojson/.travis.yml b/contrib/picojson/.travis.yml deleted file mode 100644 index e2af2ae62..000000000 --- a/contrib/picojson/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: cpp - -compiler: - - clang - - gcc - -script: - - make test diff --git a/contrib/picojson/Changes b/contrib/picojson/Changes deleted file mode 100644 index d6017ddf9..000000000 --- a/contrib/picojson/Changes +++ /dev/null @@ -1,25 +0,0 @@ -Revision history for picojson - -1.3.0 2015-02-25 13:05:00+0900 - - `make check` is now synonym of `make test` (#62) - - operator= is now safe when part of LHS is being assigned, as well as exception-safe (#66) - -1.2.1 2014-12-16 15:33:00+0900 - - bundle the contents of `picotest/` (#61) - -1.2.0 2014-12-15 16:20:00+0900 - - `make install` to install picojson.h (#58) - - two-argument `picojson::parse()` for ease-of-use (#57) - -1.1.1 2014-06-25 10:35:00+0900 - - tweaks to suppress compiler errors / warning (#38 #39) - - clarify the licenses of the files in exmaple/ (#42) - -1.1 2014-06-16 12:57:00+0900 - - added experimental support for int64 type (#34) - - by default, throw std::runtime_error instead of using assert for runtime errors (#33) - - refine compatibility regarding the use of isinf/isnan (#29, #36) - - remove `.get()` (#35) - -1.0 2014-06-05 12:54:00+0900 - - initial release with a version number diff --git a/contrib/picojson/LICENSE b/contrib/picojson/LICENSE deleted file mode 100644 index 72f355391..000000000 --- a/contrib/picojson/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright 2009-2010 Cybozu Labs, Inc. -Copyright 2011-2014 Kazuho Oku -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/picojson/Makefile b/contrib/picojson/Makefile deleted file mode 100644 index 908e2a0a0..000000000 --- a/contrib/picojson/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -prefix=/usr/local -includedir=$(prefix)/include - -check: test - -test: test-core test-core-int64 - ./test-core - ./test-core-int64 - -test-core: picojson.h test.cc picotest/picotest.c picotest/picotest.h - $(CXX) -Wall test.cc picotest/picotest.c -o $@ - -test-core-int64: picojson.h test.cc picotest/picotest.c picotest/picotest.h - $(CXX) -Wall -DPICOJSON_USE_INT64 test.cc picotest/picotest.c -o $@ - -clean: - rm -f test-core test-core-int64 - -install: - install -d $(DESTDIR)$(includedir) - install -p -m 0644 picojson.h $(DESTDIR)$(includedir) - -uninstall: - rm -f $(DESTDIR)$(includedir)/picojson.h - -.PHONY: test check clean install uninstall diff --git a/contrib/picojson/README.mkdn b/contrib/picojson/README.mkdn deleted file mode 100644 index b59fc76c3..000000000 --- a/contrib/picojson/README.mkdn +++ /dev/null @@ -1,195 +0,0 @@ -# PicoJSON - a C++ JSON parser / serializer - -Copyright © 2009-2010 Cybozu Labs, Inc. -Copyright © 2011-2015 Kazuho Oku - -Licensed under [2-clause BSD license](http://opensource.org/licenses/BSD-2-Clause) - -## Version - -1.3.1-dev [![Build Status](https://travis-ci.org/kazuho/picojson.svg?branch=master)](https://travis-ci.org/kazuho/picojson) - -## Introduction - -PicoJSON is a tiny JSON parser / serializer for C++ with following properties: - -- header-file only -- no external dependencies (only uses standard C++ libraries) -- STL-frendly (arrays are represented by using std::vector, objects are std::map) -- provides both pull interface and streaming (event-based) interface - -## Reading JSON using the pull interface - -There are several ways to use the pull (DOM-like) interface of picojson. - -The easiest way is to use the two-argument `parse` function. - -``` -std::string json = "[ \"hello JSON\" ]"; -picojson::value v; -std::string err = picojson::parse(v, json); -if (! err.empty()) { - std:cerr << err << std::endl; -} -``` - -Four-argument `parse` function accepts a pair of iterators, and returns the end position of the input. - -``` -const char* json = "{\"a\":1}"; -picojson::value v; -std::string err; -const char* json_end = picojson::parse(v, json, json + strlen(json), &err); -if (! err.empty()) { - std::cerr << err << std::endl; -} -``` - -``` -std::istream_iterator input(std::cin); -picojson::value v; -std::string err; -input = picojson::parse(v, input, std::istream_iterator(), &err); -if (! err.empty()) { - std::cerr << err << std::endl; -} -``` - -It is also possible to use the `>>` operator to parse the input, however this interface is not thread-safe. - -``` -picosjon::value v; -std::cin >> v; -std::string err = picojson::get_last_error(); -``` - -## Accessing the values - -Values of a JSON object is represented as instances of picojson::value class. - -
    -namespace picojson {
    -
    -  class value {
    -    ...
    -
    -  public:
    -
    -    typedef std::vector<value> array;
    -    typedef std::map<std::string, value> object;
    -
    -    value();                               // create a null object
    -    explicit value(bool b);                // create a boolean object
    -    explicit value(double n);              // create a number object
    -    explicit value(const std::string& s);  // create a string object
    -    explicit value(const array& a);        // create an array object
    -    explicit value(const object& o);       // create an "object"
    -
    -    bool is<picojson::null>() const;       // check if the object is "null"
    -
    -    bool is<bool>() const;                 // check if the object is a boolean
    -    const bool& get<bool>() const;         // const accessor (usable only if the object is a boolean)
    -    bool& get<bool>();                     // non-const accessor (usable only if the object is a boolean)
    -
    -    bool is<double>() const;               // check if the object is a number
    -    const double& get<double>() const;     // const accessor (usable only if the object is a number)
    -    double& get<double>();                 // non-const accessor (usable only if the object is a number)
    -
    -    bool is<std::string>() const;          // check if the object is a string
    -    const std::string& get<std::string>() const;
    -                                           // const accessor (usable only if the object is a string)
    -    std::string& get<std::string>();       // non-const accessor (usable only if the object is a string)
    -
    -    bool is<array>() const;                // check if the object is an array
    -    const array& get<array>() const;       // const accessor (usable only if the object is an array)
    -    array& get<array>();                   // non-const accessor (usable only if the object is an array)
    -
    -    bool is<object>() const;               // check if the object is an "object"
    -    const object& get<object>() const;     // const accessor (usable only if the object is an object)
    -    object& get<object>();                 // non-const accessor (usable only if the object is an array)
    -
    -    bool evaluate_as_boolean() const;      // evaluates the object as a boolean
    -
    -    std::string serialize() const;         // returns the object in JSON representation
    -    template void serialize(Iter os) const;
    -                                           // serializes the object in JSON representation through an output iterator
    -
    -    std::string to_str() const;            // returns the object in string (for casual use)
    -
    -  };
    -
    -}
    -
    - -The code below parses a JSON string and prints the contents of the object. - -
    -picojson::value v;
    -
    -// parse the input
    -std::cin >> v;
    -std::string err = picojson::get_last_error();
    -if (! err.empty()) {
    -  std::cerr << err << std::endl;
    -  exit(1);
    -}
    -
    -// check if the type of the value is "object"
    -if (! v.is<picojson::object>()) {
    -  std::cerr << "JSON is not an object" << std::endl;
    -  exit(2);
    -}
    -
    -// obtain a const reference to the map, and print the contents
    -const picojson::value::object& obj = v.get<picojson::object>();
    -for (picojson::value::object::const_iterator i = obj.begin();
    -     i != obj.end();
    -     ++i) {
    -  std::cout << i->first << ': ' << i->second.to_str() << std::endl;
    -}
    -
    - -Please note that the type check is mandatory; do not forget to check the type of the object by calling is<type>() before accessing the value by calling get<type>(). - -## Reading JSON using the streaming (event-driven) interface - -Please refer to the implementation of picojson::default_parse_context and picojson::null_parse_context. There is also an example (examples/streaming.cc) . - -## Serializing to JSON - -Instances of the picojson::value class can be serialized in three ways, to ostream, to std::string, or to an output iterator. - -
    -picojson::value v;
    -...
    -std::cout << v;
    -
    - -
    -picojson::value v;
    -...
    -std::string json = v.serialize();
    -
    - -
    -picojson::value v;
    -...
    -v.serialize(std::ostream_iterator(std::cout));
    -
    - -## Experimental support for int64_t - -Experimental suport for int64_t becomes available if the code is compiled with preprocessor macro `PICOJSON_USE_INT64`. - -Turning on the feature will cause following changes to picojson: -- new constructor `picojson::value(int64_t)` is defined -- `is()` and `get()` become available -- numerics in JSON within the bounds of int64_t and not using `.` nor `e`/`E` are considered as int64 type - - the values are also avaliable as `double`s as well (i.e. all values which are `.is() == true` are also `.is() == true`) -- int64 values are converted to double once `get()` is called - -Enabling the feature should not cause compatibility problem with code that do not use the feature. - -## Further reading - -Examples can be found in the examples directory, and on the [Wiki](https://github.com/kazuho/picojson/wiki). Please add your favorite examples to the Wiki. diff --git a/contrib/picojson/examples/github-issues.cc b/contrib/picojson/examples/github-issues.cc deleted file mode 100644 index 3e05afdc7..000000000 --- a/contrib/picojson/examples/github-issues.cc +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2009-2010 Cybozu Labs, Inc. - * Copyright 2011-2014 Kazuho Oku - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include "../picojson.h" - -typedef struct { - char* data; // response data from server - size_t size; // response size of data -} MEMFILE; - -MEMFILE* -memfopen() { - MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE)); - mf->data = NULL; - mf->size = 0; - return mf; -} - -void -memfclose(MEMFILE* mf) { - if (mf->data) free(mf->data); - free(mf); -} - -size_t -memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) { - MEMFILE* mf = (MEMFILE*) stream; - int block = size * nmemb; - if (!mf->data) - mf->data = (char*) malloc(block); - else - mf->data = (char*) realloc(mf->data, mf->size + block); - if (mf->data) { - memcpy(mf->data + mf->size, ptr, block); - mf->size += block; - } - return block; -} - -char* -memfstrdup(MEMFILE* mf) { - char* buf = (char*)malloc(mf->size + 1); - memcpy(buf, mf->data, mf->size); - buf[mf->size] = 0; - return buf; -} - -using namespace std; -using namespace picojson; - -int -main(int argc, char* argv[]) { - char error[256]; - - MEMFILE* mf = memfopen(); - CURL* curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_URL, "https://api.github.com/repos/kazuho/picojson/issues"); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl"); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf); - if (curl_easy_perform(curl) != CURLE_OK) { - cerr << error << endl; - } else { - value v; - string err; - parse(v, mf->data, mf->data + mf->size, &err); - if (err.empty()) { - array arr = v.get(); - array::iterator it; - for (it = arr.begin(); it != arr.end(); it++) { - object obj = it->get(); - cout << "#" << obj["number"].to_str() << ": " << obj["title"].to_str() << endl; - cout << " " << obj["html_url"].to_str() << endl << endl; - } - } else { - cerr << err << endl; - } - } - curl_easy_cleanup(curl); - memfclose(mf); - - return 0; -} diff --git a/contrib/picojson/examples/iostream.cc b/contrib/picojson/examples/iostream.cc deleted file mode 100644 index 30cc93fd4..000000000 --- a/contrib/picojson/examples/iostream.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2009-2010 Cybozu Labs, Inc. - * Copyright 2011-2014 Kazuho Oku - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "../picojson.h" - -int main(void) -{ - picojson::value v; - - // read json value from stream - std::cin >> v; - if (std::cin.fail()) { - std::cerr << picojson::get_last_error() << std::endl; - return 1; - } - - // dump json object - std::cout << "---- dump input ----" << std::endl; - std::cout << v << std::endl; - - // accessors - std::cout << "---- analyzing input ----" << std::endl; - if (v.is()) { - std::cout << "input is null" << std::endl; - } else if (v.is()) { - std::cout << "input is " << (v.get() ? "true" : "false") << std::endl; - } else if (v.is()) { - std::cout << "input is " << v.get() << std::endl; - } else if (v.is()) { - std::cout << "input is " << v.get() << std::endl; - } else if (v.is()) { - std::cout << "input is an array" << std::endl; - const picojson::array& a = v.get(); - for (picojson::array::const_iterator i = a.begin(); i != a.end(); ++i) { - std::cout << " " << *i << std::endl; - } - } else if (v.is()) { - std::cout << "input is an object" << std::endl; - const picojson::object& o = v.get(); - for (picojson::object::const_iterator i = o.begin(); i != o.end(); ++i) { - std::cout << i->first << " " << i->second << std::endl; - } - } - - return 0; -} diff --git a/contrib/picojson/examples/streaming.cc b/contrib/picojson/examples/streaming.cc deleted file mode 100644 index 8b1225f31..000000000 --- a/contrib/picojson/examples/streaming.cc +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2009-2010 Cybozu Labs, Inc. - * Copyright 2011-2014 Kazuho Oku - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include -#include "../picojson.h" - -// this example reads a array of hashes (each item representing a 2D point), -// and prints the x and y values to stdout - -namespace { - - class root_context : public picojson::deny_parse_context { - public: - bool parse_array_start() { - return true; // only allow array as root - } - template bool parse_array_item(picojson::input& in, size_t) { - picojson::value item; - // parse the array item - picojson::default_parse_context ctx(&item); - if (! picojson::_parse(ctx, in)) { - return false; - } - // assert that the array item is a hash - if (! item.is()) { - return false; - } - // print x and y - std::cout << item.get("x") << ',' << item.get("y").to_str() - << std::endl; - return true; - } - }; - -} - -int main(void) -{ - root_context ctx; - std::string err; - - picojson::_parse(ctx, std::istream_iterator(std::cin), - std::istream_iterator(), &err); - - if (! err.empty()) { - std::cerr << err << std::endl; - return 1; - } - - return 0; -} diff --git a/contrib/picojson/picojson.h b/contrib/picojson/picojson.h deleted file mode 100644 index 045dc537b..000000000 --- a/contrib/picojson/picojson.h +++ /dev/null @@ -1,1039 +0,0 @@ -/* - * Copyright 2009-2010 Cybozu Labs, Inc. - * Copyright 2011-2014 Kazuho Oku - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef picojson_h -#define picojson_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// for isnan/isinf -#if __cplusplus>=201103L -# include -#else -extern "C" { -# ifdef _MSC_VER -# include -# elif defined(__INTEL_COMPILER) -# include -# else -# include -# endif -} -#endif - -#ifndef PICOJSON_USE_RVALUE_REFERENCE -# if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || (defined(_MSC_VER) && _MSC_VER >= 1600) -# define PICOJSON_USE_RVALUE_REFERENCE 1 -# else -# define PICOJSON_USE_RVALUE_REFERENCE 0 -# endif -#endif//PICOJSON_USE_RVALUE_REFERENCE - - -// experimental support for int64_t (see README.mkdn for detail) -#ifdef PICOJSON_USE_INT64 -# define __STDC_FORMAT_MACROS -# include -# include -#endif - -// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0 -#ifndef PICOJSON_USE_LOCALE -# define PICOJSON_USE_LOCALE 1 -#endif -#if PICOJSON_USE_LOCALE -extern "C" { -# include -} -#endif - -#ifndef PICOJSON_ASSERT -# define PICOJSON_ASSERT(e) do { if (! (e)) throw std::runtime_error(#e); } while (0) -#endif - -#ifdef _MSC_VER - #define SNPRINTF _snprintf_s - #pragma warning(push) - #pragma warning(disable : 4244) // conversion from int to char - #pragma warning(disable : 4127) // conditional expression is constant - #pragma warning(disable : 4702) // unreachable code -#else - #define SNPRINTF snprintf -#endif - -namespace picojson { - - enum { - null_type, - boolean_type, - number_type, - string_type, - array_type, - object_type -#ifdef PICOJSON_USE_INT64 - , int64_type -#endif - }; - - enum { - INDENT_WIDTH = 2 - }; - - struct null {}; - - class value { - public: - typedef std::vector array; - typedef std::map object; - union _storage { - bool boolean_; - double number_; -#ifdef PICOJSON_USE_INT64 - int64_t int64_; -#endif - std::string* string_; - array* array_; - object* object_; - }; - protected: - int type_; - _storage u_; - public: - value(); - value(int type, bool); - explicit value(bool b); -#ifdef PICOJSON_USE_INT64 - explicit value(int64_t i); -#endif - explicit value(double n); - explicit value(const std::string& s); - explicit value(const array& a); - explicit value(const object& o); - explicit value(const char* s); - value(const char* s, size_t len); - ~value(); - value(const value& x); - value& operator=(const value& x); -#if PICOJSON_USE_RVALUE_REFERENCE - value(value&& x)throw(); - value& operator=(value&& x)throw(); -#endif - void swap(value& x)throw(); - template bool is() const; - template const T& get() const; - template T& get(); - bool evaluate_as_boolean() const; - const value& get(size_t idx) const; - const value& get(const std::string& key) const; - value& get(size_t idx); - value& get(const std::string& key); - - bool contains(size_t idx) const; - bool contains(const std::string& key) const; - std::string to_str() const; - template void serialize(Iter os, bool prettify = false) const; - std::string serialize(bool prettify = false) const; - private: - template value(const T*); // intentionally defined to block implicit conversion of pointer to bool - template static void _indent(Iter os, int indent); - template void _serialize(Iter os, int indent) const; - std::string _serialize(int indent) const; - }; - - typedef value::array array; - typedef value::object object; - - inline value::value() : type_(null_type) {} - - inline value::value(int type, bool) : type_(type) { - switch (type) { -#define INIT(p, v) case p##type: u_.p = v; break - INIT(boolean_, false); - INIT(number_, 0.0); -#ifdef PICOJSON_USE_INT64 - INIT(int64_, 0); -#endif - INIT(string_, new std::string()); - INIT(array_, new array()); - INIT(object_, new object()); -#undef INIT - default: break; - } - } - - inline value::value(bool b) : type_(boolean_type) { - u_.boolean_ = b; - } - -#ifdef PICOJSON_USE_INT64 - inline value::value(int64_t i) : type_(int64_type) { - u_.int64_ = i; - } -#endif - - inline value::value(double n) : type_(number_type) { - if ( -#ifdef _MSC_VER - ! _finite(n) -#elif __cplusplus>=201103L || !(defined(isnan) && defined(isinf)) - std::isnan(n) || std::isinf(n) -#else - isnan(n) || isinf(n) -#endif - ) { - throw std::overflow_error(""); - } - u_.number_ = n; - } - - inline value::value(const std::string& s) : type_(string_type) { - u_.string_ = new std::string(s); - } - - inline value::value(const array& a) : type_(array_type) { - u_.array_ = new array(a); - } - - inline value::value(const object& o) : type_(object_type) { - u_.object_ = new object(o); - } - - inline value::value(const char* s) : type_(string_type) { - u_.string_ = new std::string(s); - } - - inline value::value(const char* s, size_t len) : type_(string_type) { - u_.string_ = new std::string(s, len); - } - - inline value::~value() { - switch (type_) { -#define DEINIT(p) case p##type: delete u_.p; break - DEINIT(string_); - DEINIT(array_); - DEINIT(object_); -#undef DEINIT - default: break; - } - } - - inline value::value(const value& x) : type_(x.type_) { - switch (type_) { -#define INIT(p, v) case p##type: u_.p = v; break - INIT(string_, new std::string(*x.u_.string_)); - INIT(array_, new array(*x.u_.array_)); - INIT(object_, new object(*x.u_.object_)); -#undef INIT - default: - u_ = x.u_; - break; - } - } - - inline value& value::operator=(const value& x) { - if (this != &x) { - value t(x); - swap(t); - } - return *this; - } - -#if PICOJSON_USE_RVALUE_REFERENCE - inline value::value(value&& x)throw() : type_(null_type) { - swap(x); - } - inline value& value::operator=(value&& x)throw() { - swap(x); - return *this; - } -#endif - inline void value::swap(value& x)throw() { - std::swap(type_, x.type_); - std::swap(u_, x.u_); - } - -#define IS(ctype, jtype) \ - template <> inline bool value::is() const { \ - return type_ == jtype##_type; \ - } - IS(null, null) - IS(bool, boolean) -#ifdef PICOJSON_USE_INT64 - IS(int64_t, int64) -#endif - IS(std::string, string) - IS(array, array) - IS(object, object) -#undef IS - template <> inline bool value::is() const { - return type_ == number_type -#ifdef PICOJSON_USE_INT64 - || type_ == int64_type -#endif - ; - } - -#define GET(ctype, var) \ - template <> inline const ctype& value::get() const { \ - PICOJSON_ASSERT("type mismatch! call is() before get()" \ - && is()); \ - return var; \ - } \ - template <> inline ctype& value::get() { \ - PICOJSON_ASSERT("type mismatch! call is() before get()" \ - && is()); \ - return var; \ - } - GET(bool, u_.boolean_) - GET(std::string, *u_.string_) - GET(array, *u_.array_) - GET(object, *u_.object_) -#ifdef PICOJSON_USE_INT64 - GET(double, (type_ == int64_type && (const_cast(this)->type_ = number_type, const_cast(this)->u_.number_ = u_.int64_), u_.number_)) - GET(int64_t, u_.int64_) -#else - GET(double, u_.number_) -#endif -#undef GET - - inline bool value::evaluate_as_boolean() const { - switch (type_) { - case null_type: - return false; - case boolean_type: - return u_.boolean_; - case number_type: - return u_.number_ != 0; -#ifdef PICOJSON_USE_INT64 - case int64_type: - return u_.int64_ != 0; -#endif - case string_type: - return ! u_.string_->empty(); - default: - return true; - } - } - - inline const value& value::get(size_t idx) const { - static value s_null; - PICOJSON_ASSERT(is()); - return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; - } - - inline value& value::get(size_t idx) { - static value s_null; - PICOJSON_ASSERT(is()); - return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; - } - - inline const value& value::get(const std::string& key) const { - static value s_null; - PICOJSON_ASSERT(is()); - object::const_iterator i = u_.object_->find(key); - return i != u_.object_->end() ? i->second : s_null; - } - - inline value& value::get(const std::string& key) { - static value s_null; - PICOJSON_ASSERT(is()); - object::iterator i = u_.object_->find(key); - return i != u_.object_->end() ? i->second : s_null; - } - - inline bool value::contains(size_t idx) const { - PICOJSON_ASSERT(is()); - return idx < u_.array_->size(); - } - - inline bool value::contains(const std::string& key) const { - PICOJSON_ASSERT(is()); - object::const_iterator i = u_.object_->find(key); - return i != u_.object_->end(); - } - - inline std::string value::to_str() const { - switch (type_) { - case null_type: return "null"; - case boolean_type: return u_.boolean_ ? "true" : "false"; -#ifdef PICOJSON_USE_INT64 - case int64_type: { - char buf[sizeof("-9223372036854775808")]; - SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_); - return buf; - } -#endif - case number_type: { - char buf[256]; - double tmp; - SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_); -#if PICOJSON_USE_LOCALE - char *decimal_point = localeconv()->decimal_point; - if (strcmp(decimal_point, ".") != 0) { - size_t decimal_point_len = strlen(decimal_point); - for (char *p = buf; *p != '\0'; ++p) { - if (strncmp(p, decimal_point, decimal_point_len) == 0) { - return std::string(buf, p) + "." + (p + decimal_point_len); - } - } - } -#endif - return buf; - } - case string_type: return *u_.string_; - case array_type: return "array"; - case object_type: return "object"; - default: PICOJSON_ASSERT(0); -#ifdef _MSC_VER - __assume(0); -#endif - } - return std::string(); - } - - template void copy(const std::string& s, Iter oi) { - std::copy(s.begin(), s.end(), oi); - } - - template void serialize_str(const std::string& s, Iter oi) { - *oi++ = '"'; - for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { - switch (*i) { -#define MAP(val, sym) case val: copy(sym, oi); break - MAP('"', "\\\""); - MAP('\\', "\\\\"); - MAP('/', "\\/"); - MAP('\b', "\\b"); - MAP('\f', "\\f"); - MAP('\n', "\\n"); - MAP('\r', "\\r"); - MAP('\t', "\\t"); -#undef MAP - default: - if (static_cast(*i) < 0x20 || *i == 0x7f) { - char buf[7]; - SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff); - copy(buf, buf + 6, oi); - } else { - *oi++ = *i; - } - break; - } - } - *oi++ = '"'; - } - - template void value::serialize(Iter oi, bool prettify) const { - return _serialize(oi, prettify ? 0 : -1); - } - - inline std::string value::serialize(bool prettify) const { - return _serialize(prettify ? 0 : -1); - } - - template void value::_indent(Iter oi, int indent) { - *oi++ = '\n'; - for (int i = 0; i < indent * INDENT_WIDTH; ++i) { - *oi++ = ' '; - } - } - - template void value::_serialize(Iter oi, int indent) const { - switch (type_) { - case string_type: - serialize_str(*u_.string_, oi); - break; - case array_type: { - *oi++ = '['; - if (indent != -1) { - ++indent; - } - for (array::const_iterator i = u_.array_->begin(); - i != u_.array_->end(); - ++i) { - if (i != u_.array_->begin()) { - *oi++ = ','; - } - if (indent != -1) { - _indent(oi, indent); - } - i->_serialize(oi, indent); - } - if (indent != -1) { - --indent; - if (! u_.array_->empty()) { - _indent(oi, indent); - } - } - *oi++ = ']'; - break; - } - case object_type: { - *oi++ = '{'; - if (indent != -1) { - ++indent; - } - for (object::const_iterator i = u_.object_->begin(); - i != u_.object_->end(); - ++i) { - if (i != u_.object_->begin()) { - *oi++ = ','; - } - if (indent != -1) { - _indent(oi, indent); - } - serialize_str(i->first, oi); - *oi++ = ':'; - if (indent != -1) { - *oi++ = ' '; - } - i->second._serialize(oi, indent); - } - if (indent != -1) { - --indent; - if (! u_.object_->empty()) { - _indent(oi, indent); - } - } - *oi++ = '}'; - break; - } - default: - copy(to_str(), oi); - break; - } - if (indent == 0) { - *oi++ = '\n'; - } - } - - inline std::string value::_serialize(int indent) const { - std::string s; - _serialize(std::back_inserter(s), indent); - return s; - } - - template class input { - protected: - Iter cur_, end_; - int last_ch_; - bool ungot_; - int line_; - public: - input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {} - int getc() { - if (ungot_) { - ungot_ = false; - return last_ch_; - } - if (cur_ == end_) { - last_ch_ = -1; - return -1; - } - if (last_ch_ == '\n') { - line_++; - } - last_ch_ = *cur_ & 0xff; - ++cur_; - return last_ch_; - } - void ungetc() { - if (last_ch_ != -1) { - PICOJSON_ASSERT(! ungot_); - ungot_ = true; - } - } - Iter cur() const { return cur_; } - int line() const { return line_; } - void skip_ws() { - while (1) { - int ch = getc(); - if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { - ungetc(); - break; - } - } - } - bool expect(int expect) { - skip_ws(); - if (getc() != expect) { - ungetc(); - return false; - } - return true; - } - bool match(const std::string& pattern) { - for (std::string::const_iterator pi(pattern.begin()); - pi != pattern.end(); - ++pi) { - if (getc() != *pi) { - ungetc(); - return false; - } - } - return true; - } - }; - - template inline int _parse_quadhex(input &in) { - int uni_ch = 0, hex; - for (int i = 0; i < 4; i++) { - if ((hex = in.getc()) == -1) { - return -1; - } - if ('0' <= hex && hex <= '9') { - hex -= '0'; - } else if ('A' <= hex && hex <= 'F') { - hex -= 'A' - 0xa; - } else if ('a' <= hex && hex <= 'f') { - hex -= 'a' - 0xa; - } else { - in.ungetc(); - return -1; - } - uni_ch = uni_ch * 16 + hex; - } - return uni_ch; - } - - template inline bool _parse_codepoint(String& out, input& in) { - int uni_ch; - if ((uni_ch = _parse_quadhex(in)) == -1) { - return false; - } - if (0xd800 <= uni_ch && uni_ch <= 0xdfff) { - if (0xdc00 <= uni_ch) { - // a second 16-bit of a surrogate pair appeared - return false; - } - // first 16-bit of surrogate pair, get the next one - if (in.getc() != '\\' || in.getc() != 'u') { - in.ungetc(); - return false; - } - int second = _parse_quadhex(in); - if (! (0xdc00 <= second && second <= 0xdfff)) { - return false; - } - uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff); - uni_ch += 0x10000; - } - if (uni_ch < 0x80) { - out.push_back(uni_ch); - } else { - if (uni_ch < 0x800) { - out.push_back(0xc0 | (uni_ch >> 6)); - } else { - if (uni_ch < 0x10000) { - out.push_back(0xe0 | (uni_ch >> 12)); - } else { - out.push_back(0xf0 | (uni_ch >> 18)); - out.push_back(0x80 | ((uni_ch >> 12) & 0x3f)); - } - out.push_back(0x80 | ((uni_ch >> 6) & 0x3f)); - } - out.push_back(0x80 | (uni_ch & 0x3f)); - } - return true; - } - - template inline bool _parse_string(String& out, input& in) { - while (1) { - int ch = in.getc(); - if (ch < ' ') { - in.ungetc(); - return false; - } else if (ch == '"') { - return true; - } else if (ch == '\\') { - if ((ch = in.getc()) == -1) { - return false; - } - switch (ch) { -#define MAP(sym, val) case sym: out.push_back(val); break - MAP('"', '\"'); - MAP('\\', '\\'); - MAP('/', '/'); - MAP('b', '\b'); - MAP('f', '\f'); - MAP('n', '\n'); - MAP('r', '\r'); - MAP('t', '\t'); -#undef MAP - case 'u': - if (! _parse_codepoint(out, in)) { - return false; - } - break; - default: - return false; - } - } else { - out.push_back(ch); - } - } - return false; - } - - template inline bool _parse_array(Context& ctx, input& in) { - if (! ctx.parse_array_start()) { - return false; - } - size_t idx = 0; - if (in.expect(']')) { - return ctx.parse_array_stop(idx); - } - do { - if (! ctx.parse_array_item(in, idx)) { - return false; - } - idx++; - } while (in.expect(',')); - return in.expect(']') && ctx.parse_array_stop(idx); - } - - template inline bool _parse_object(Context& ctx, input& in) { - if (! ctx.parse_object_start()) { - return false; - } - if (in.expect('}')) { - return true; - } - do { - std::string key; - if (! in.expect('"') - || ! _parse_string(key, in) - || ! in.expect(':')) { - return false; - } - if (! ctx.parse_object_item(in, key)) { - return false; - } - } while (in.expect(',')); - return in.expect('}'); - } - - template inline std::string _parse_number(input& in) { - std::string num_str; - while (1) { - int ch = in.getc(); - if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' - || ch == 'e' || ch == 'E') { - num_str.push_back(ch); - } else if (ch == '.') { -#if PICOJSON_USE_LOCALE - num_str += localeconv()->decimal_point; -#else - num_str.push_back('.'); -#endif - } else { - in.ungetc(); - break; - } - } - return num_str; - } - - template inline bool _parse(Context& ctx, input& in) { - in.skip_ws(); - int ch = in.getc(); - switch (ch) { -#define IS(ch, text, op) case ch: \ - if (in.match(text) && op) { \ - return true; \ - } else { \ - return false; \ - } - IS('n', "ull", ctx.set_null()); - IS('f', "alse", ctx.set_bool(false)); - IS('t', "rue", ctx.set_bool(true)); -#undef IS - case '"': - return ctx.parse_string(in); - case '[': - return _parse_array(ctx, in); - case '{': - return _parse_object(ctx, in); - default: - if (('0' <= ch && ch <= '9') || ch == '-') { - double f; - char *endp; - in.ungetc(); - std::string num_str = _parse_number(in); - if (num_str.empty()) { - return false; - } -#ifdef PICOJSON_USE_INT64 - { - errno = 0; - intmax_t ival = strtoimax(num_str.c_str(), &endp, 10); - if (errno == 0 - && std::numeric_limits::min() <= ival - && ival <= std::numeric_limits::max() - && endp == num_str.c_str() + num_str.size()) { - ctx.set_int64(ival); - return true; - } - } -#endif - f = strtod(num_str.c_str(), &endp); - if (endp == num_str.c_str() + num_str.size()) { - ctx.set_number(f); - return true; - } - return false; - } - break; - } - in.ungetc(); - return false; - } - - class deny_parse_context { - public: - bool set_null() { return false; } - bool set_bool(bool) { return false; } -#ifdef PICOJSON_USE_INT64 - bool set_int64(int64_t) { return false; } -#endif - bool set_number(double) { return false; } - template bool parse_string(input&) { return false; } - bool parse_array_start() { return false; } - template bool parse_array_item(input&, size_t) { - return false; - } - bool parse_array_stop(size_t) { return false; } - bool parse_object_start() { return false; } - template bool parse_object_item(input&, const std::string&) { - return false; - } - }; - - class default_parse_context { - protected: - value* out_; - public: - default_parse_context(value* out) : out_(out) {} - bool set_null() { - *out_ = value(); - return true; - } - bool set_bool(bool b) { - *out_ = value(b); - return true; - } -#ifdef PICOJSON_USE_INT64 - bool set_int64(int64_t i) { - *out_ = value(i); - return true; - } -#endif - bool set_number(double f) { - *out_ = value(f); - return true; - } - template bool parse_string(input& in) { - *out_ = value(string_type, false); - return _parse_string(out_->get(), in); - } - bool parse_array_start() { - *out_ = value(array_type, false); - return true; - } - template bool parse_array_item(input& in, size_t) { - array& a = out_->get(); - a.push_back(value()); - default_parse_context ctx(&a.back()); - return _parse(ctx, in); - } - bool parse_array_stop(size_t) { return true; } - bool parse_object_start() { - *out_ = value(object_type, false); - return true; - } - template bool parse_object_item(input& in, const std::string& key) { - object& o = out_->get(); - default_parse_context ctx(&o[key]); - return _parse(ctx, in); - } - private: - default_parse_context(const default_parse_context&); - default_parse_context& operator=(const default_parse_context&); - }; - - class null_parse_context { - public: - struct dummy_str { - void push_back(int) {} - }; - public: - null_parse_context() {} - bool set_null() { return true; } - bool set_bool(bool) { return true; } -#ifdef PICOJSON_USE_INT64 - bool set_int64(int64_t) { return true; } -#endif - bool set_number(double) { return true; } - template bool parse_string(input& in) { - dummy_str s; - return _parse_string(s, in); - } - bool parse_array_start() { return true; } - template bool parse_array_item(input& in, size_t) { - return _parse(*this, in); - } - bool parse_array_stop(size_t) { return true; } - bool parse_object_start() { return true; } - template bool parse_object_item(input& in, const std::string&) { - return _parse(*this, in); - } - private: - null_parse_context(const null_parse_context&); - null_parse_context& operator=(const null_parse_context&); - }; - - // obsolete, use the version below - template inline std::string parse(value& out, Iter& pos, const Iter& last) { - std::string err; - pos = parse(out, pos, last, &err); - return err; - } - - template inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::string* err) { - input in(first, last); - if (! _parse(ctx, in) && err != NULL) { - char buf[64]; - SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line()); - *err = buf; - while (1) { - int ch = in.getc(); - if (ch == -1 || ch == '\n') { - break; - } else if (ch >= ' ') { - err->push_back(ch); - } - } - } - return in.cur(); - } - - template inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err) { - default_parse_context ctx(&out); - return _parse(ctx, first, last, err); - } - - inline std::string parse(value& out, const std::string& s) { - std::string err; - parse(out, s.begin(), s.end(), &err); - return err; - } - - inline std::string parse(value& out, std::istream& is) { - std::string err; - parse(out, std::istreambuf_iterator(is.rdbuf()), - std::istreambuf_iterator(), &err); - return err; - } - - template struct last_error_t { - static std::string s; - }; - template std::string last_error_t::s; - - inline void set_last_error(const std::string& s) { - last_error_t::s = s; - } - - inline const std::string& get_last_error() { - return last_error_t::s; - } - - inline bool operator==(const value& x, const value& y) { - if (x.is()) - return y.is(); -#define PICOJSON_CMP(type) \ - if (x.is()) \ - return y.is() && x.get() == y.get() - PICOJSON_CMP(bool); - PICOJSON_CMP(double); - PICOJSON_CMP(std::string); - PICOJSON_CMP(array); - PICOJSON_CMP(object); -#undef PICOJSON_CMP - PICOJSON_ASSERT(0); -#ifdef _MSC_VER - __assume(0); -#endif - return false; - } - - inline bool operator!=(const value& x, const value& y) { - return ! (x == y); - } -} - -#if !PICOJSON_USE_RVALUE_REFERENCE -namespace std { - template<> inline void swap(picojson::value& x, picojson::value& y) - { - x.swap(y); - } -} -#endif - -inline std::istream& operator>>(std::istream& is, picojson::value& x) -{ - picojson::set_last_error(std::string()); - std::string err = picojson::parse(x, is); - if (! err.empty()) { - picojson::set_last_error(err); - is.setstate(std::ios::failbit); - } - return is; -} - -inline std::ostream& operator<<(std::ostream& os, const picojson::value& x) -{ - x.serialize(std::ostream_iterator(os)); - return os; -} -#ifdef _MSC_VER - #pragma warning(pop) -#endif - -#endif diff --git a/contrib/picojson/picotest/picotest.c b/contrib/picojson/picotest/picotest.c deleted file mode 100644 index d1fe699d5..000000000 --- a/contrib/picojson/picotest/picotest.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2014 DeNA Co., Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include -#include -#include -#include "picotest.h" - -struct test_t { - int num_tests; - int failed; -}; -struct test_t main_tests, *cur_tests = &main_tests; -static int test_level = 0; - -static void indent(void) -{ - int i; - for (i = 0; i != test_level; ++i) - printf(" "); -} - -__attribute__((format (printf, 1, 2))) -void note(const char *fmt, ...) -{ - va_list arg; - - indent(); - printf("# "); - - va_start(arg, fmt); - vprintf(fmt, arg); - va_end(arg); - - printf("\n"); -} - -__attribute__((format (printf, 2, 3))) -void _ok(int cond, const char *fmt, ...) -{ - va_list arg; - - if (! cond) - cur_tests->failed = 1; - indent(); - - printf("%s %d - ", cond ? "ok" : "not ok", ++cur_tests->num_tests); - va_start(arg, fmt); - vprintf(fmt, arg); - va_end(arg); - - printf("\n"); -} - -int done_testing(void) -{ - indent(); - printf("1..%d\n", cur_tests->num_tests); - return cur_tests->failed; -} - -void subtest(const char *name, void (*cb)(void)) -{ - struct test_t test = {}, *parent_tests; - - parent_tests = cur_tests; - cur_tests = &test; - ++test_level; - - note("Subtest: %s", name); - - cb(); - - done_testing(); - - --test_level; - cur_tests = parent_tests; - if (test.failed) - cur_tests->failed = 1; - _ok(! test.failed, "%s", name); -} diff --git a/contrib/picojson/picotest/picotest.h b/contrib/picojson/picotest/picotest.h deleted file mode 100644 index 22ab02fb2..000000000 --- a/contrib/picojson/picotest/picotest.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2014 DeNA Co., Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#ifndef picotest_h -#define picotest_h - -#ifdef __cplusplus -extern "C" { -#endif - -void note(const char *fmt, ...) __attribute__((format (printf, 1, 2))); -void _ok(int cond, const char *fmt, ...) __attribute__((format (printf, 2, 3))); -#define ok(cond) _ok(cond, "%s %d", __FILE__, __LINE__) -int done_testing(void); -void subtest(const char *name, void (*cb)(void)); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/contrib/picojson/test.cc b/contrib/picojson/test.cc deleted file mode 100644 index 73260ca94..000000000 --- a/contrib/picojson/test.cc +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright 2009-2010 Cybozu Labs, Inc. - * Copyright 2011-2014 Kazuho Oku, Yasuhiro Matsumoto, Shigeo Mitsunari - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "picojson.h" -#include "picotest/picotest.h" - -#ifdef _MSC_VER - #pragma warning(disable : 4127) // conditional expression is constant -#endif - -using namespace std; - -#define is(x, y, name) _ok((x) == (y), name) - -#include -#include -#include -#include - -int main(void) -{ -#if PICOJSON_USE_LOCALE - setlocale(LC_ALL, ""); -#endif - - // constructors -#define TEST(expr, expected) \ - is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr) - - TEST( (true), "true"); - TEST( (false), "false"); - TEST( (42.0), "42"); - TEST( (string("hello")), "\"hello\""); - TEST( ("hello"), "\"hello\""); - TEST( ("hello", 4), "\"hell\""); - - { - double a = 1; - for (int i = 0; i < 1024; i++) { - picojson::value vi(a); - std::stringstream ss; - ss << vi; - picojson::value vo; - ss >> vo; - double b = vo.get(); - if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) { - printf("ng i=%d a=%.18e b=%.18e\n", i, a, b); - } - a *= 2; - } - } - -#undef TEST - -#define TEST(in, type, cmp, serialize_test) { \ - picojson::value v; \ - const char* s = in; \ - string err = picojson::parse(v, s, s + strlen(s)); \ - _ok(err.empty(), in " no error"); \ - _ok(v.is(), in " check type"); \ - is(v.get(), static_cast(cmp), in " correct output"); \ - is(*s, '\0', in " read to eof"); \ - if (serialize_test) { \ - is(v.serialize(), string(in), in " serialize"); \ - } \ - } - TEST("false", bool, false, true); - TEST("true", bool, true, true); - TEST("90.5", double, 90.5, false); - TEST("1.7976931348623157e+308", double, DBL_MAX, false); - TEST("\"hello\"", string, string("hello"), true); - TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"), - true); - TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string, - string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false); - TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false); -#ifdef PICOJSON_USE_INT64 - TEST("0", int64_t, 0, true); - TEST("-9223372036854775808", int64_t, std::numeric_limits::min(), true); - TEST("9223372036854775807", int64_t, std::numeric_limits::max(), true); -#endif -#undef TEST - -#define TEST(type, expr) { \ - picojson::value v; \ - const char *s = expr; \ - string err = picojson::parse(v, s, s + strlen(s)); \ - _ok(err.empty(), "empty " #type " no error"); \ - _ok(v.is(), "empty " #type " check type"); \ - _ok(v.get().empty(), "check " #type " array size"); \ - } - TEST(array, "[]"); - TEST(object, "{}"); -#undef TEST - - { - picojson::value v; - const char *s = "[1,true,\"hello\"]"; - string err = picojson::parse(v, s, s + strlen(s)); - _ok(err.empty(), "array no error"); - _ok(v.is(), "array check type"); - is(v.get().size(), size_t(3), "check array size"); - _ok(v.contains(0), "check contains array[0]"); - _ok(v.get(0).is(), "check array[0] type"); - is(v.get(0).get(), 1.0, "check array[0] value"); - _ok(v.contains(1), "check contains array[1]"); - _ok(v.get(1).is(), "check array[1] type"); - _ok(v.get(1).get(), "check array[1] value"); - _ok(v.contains(2), "check contains array[2]"); - _ok(v.get(2).is(), "check array[2] type"); - is(v.get(2).get(), string("hello"), "check array[2] value"); - _ok(!v.contains(3), "check not contains array[3]"); - } - - { - picojson::value v; - const char *s = "{ \"a\": true }"; - string err = picojson::parse(v, s, s + strlen(s)); - _ok(err.empty(), "object no error"); - _ok(v.is(), "object check type"); - is(v.get().size(), size_t(1), "check object size"); - _ok(v.contains("a"), "check contains property"); - _ok(v.get("a").is(), "check bool property exists"); - is(v.get("a").get(), true, "check bool property value"); - is(v.serialize(), string("{\"a\":true}"), "serialize object"); - _ok(!v.contains("z"), "check not contains property"); - } - -#define TEST(json, msg) do { \ - picojson::value v; \ - const char *s = json; \ - string err = picojson::parse(v, s, s + strlen(s)); \ - is(err, string("syntax error at line " msg), msg); \ - } while (0) - TEST("falsoa", "1 near: oa"); - TEST("{]", "1 near: ]"); - TEST("\n\bbell", "2 near: bell"); - TEST("\"abc\nd\"", "1 near: "); -#undef TEST - - { - picojson::value v1, v2; - const char *s; - string err; - s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; - err = picojson::parse(v1, s, s + strlen(s)); - s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }"; - err = picojson::parse(v2, s, s + strlen(s)); - _ok((v1 == v2), "check == operator in deep comparison"); - } - - { - picojson::value v1, v2; - const char *s; - string err; - s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; - err = picojson::parse(v1, s, s + strlen(s)); - s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }"; - err = picojson::parse(v2, s, s + strlen(s)); - _ok((v1 != v2), "check != operator for array in deep comparison"); - } - - { - picojson::value v1, v2; - const char *s; - string err; - s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; - err = picojson::parse(v1, s, s + strlen(s)); - s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }"; - err = picojson::parse(v2, s, s + strlen(s)); - _ok((v1 != v2), "check != operator for object in deep comparison"); - } - - { - picojson::value v1, v2; - const char *s; - string err; - s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; - err = picojson::parse(v1, s, s + strlen(s)); - picojson::object& o = v1.get(); - o.erase("b"); - picojson::array& a = o["a"].get(); - picojson::array::iterator i; - i = std::remove(a.begin(), a.end(), picojson::value(std::string("three"))); - a.erase(i, a.end()); - s = "{ \"a\": [1,2], \"d\": 2 }"; - err = picojson::parse(v2, s, s + strlen(s)); - _ok((v1 == v2), "check erase()"); - } - - _ok(picojson::value(3.0).serialize() == "3", - "integral number should be serialized as a integer"); - - { - const char* s = "{ \"a\": [1,2], \"d\": 2 }"; - picojson::null_parse_context ctx; - string err; - picojson::_parse(ctx, s, s + strlen(s), &err); - _ok(err.empty(), "null_parse_context"); - } - - { - picojson::value v1, v2; - v1 = picojson::value(true); - swap(v1, v2); - _ok(v1.is(), "swap (null)"); - _ok(v2.get() == true, "swap (bool)"); - - v1 = picojson::value("a"); - v2 = picojson::value(1.0); - swap(v1, v2); - _ok(v1.get() == 1.0, "swap (dobule)"); - _ok(v2.get() == "a", "swap (string)"); - - v1 = picojson::value(picojson::object()); - v2 = picojson::value(picojson::array()); - swap(v1, v2); - _ok(v1.is(), "swap (array)"); - _ok(v2.is(), "swap (object)"); - } - - { - picojson::value v; - const char *s = "{ \"a\": 1, \"b\": [ 2, { \"b1\": \"abc\" } ], \"c\": {}, \"d\": [] }"; - string err; - err = picojson::parse(v, s, s + strlen(s)); - _ok(err.empty(), "parse test data for prettifying output"); - _ok(v.serialize() == "{\"a\":1,\"b\":[2,{\"b1\":\"abc\"}],\"c\":{},\"d\":[]}", "non-prettifying output"); - _ok(v.serialize(true) == "{\n \"a\": 1,\n \"b\": [\n 2,\n {\n \"b1\": \"abc\"\n }\n ],\n \"c\": {},\n \"d\": []\n}\n", "prettifying output"); - } - - try { - picojson::value v(std::numeric_limits::quiet_NaN()); - _ok(false, "should not accept NaN"); - } catch (std::overflow_error e) { - _ok(true, "should not accept NaN"); - } - - try { - picojson::value v(std::numeric_limits::infinity()); - _ok(false, "should not accept infinity"); - } catch (std::overflow_error e) { - _ok(true, "should not accept infinity"); - } - - try { - picojson::value v(123.); - _ok(! v.is(), "is() should return false"); - v.get(); - _ok(false, "get() should raise an error"); - } catch (std::runtime_error e) { - _ok(true, "get() should raise an error"); - } - -#ifdef PICOJSON_USE_INT64 - { - picojson::value v1((int64_t)123); - _ok(v1.is(), "is int64_t"); - _ok(v1.is(), "is double as well"); - _ok(v1.serialize() == "123", "serialize the value"); - _ok(v1.get() == 123, "value is correct as int64_t"); - _ok(v1.get(), "value is correct as double"); - - _ok(! v1.is(), "is no more int64_type once get() is called"); - _ok(v1.is(), "and is still a double"); - - const char *s = "-9223372036854775809"; - _ok(picojson::parse(v1, s, s + strlen(s)).empty(), "parse underflowing int64_t"); - _ok(! v1.is(), "underflowing int is not int64_t"); - _ok(v1.is(), "underflowing int is double"); - _ok(v1.get() + 9.22337203685478e+18 < 65536, "double value is somewhat correct"); - } -#endif - - { - picojson::value v; - std::string err = picojson::parse(v, "[ 1, \"abc\" ]"); - _ok(err.empty(), "simple API no error"); - _ok(v.is(), "simple API return type is array"); - is(v.get().size(), 2, "simple API array size"); - _ok(v.get()[0].is(), "simple API type #0"); - is(v.get()[0].get(), 1, "simple API value #0"); - _ok(v.get()[1].is(), "simple API type #1"); - is(v.get()[1].get(), "abc", "simple API value #1"); - } - - { - picojson::value v1((double) 0); - _ok(! v1.evaluate_as_boolean(), "((double) 0) is false"); - picojson::value v2((double) 1); - _ok(v2.evaluate_as_boolean(), "((double) 1) is true"); -#ifdef PICOJSON_USE_INT64 - picojson::value v3((int64_t) 0); - _ok(! v3.evaluate_as_boolean(), "((int64_t) 0) is false"); - picojson::value v4((int64_t) 1); - _ok(v4.evaluate_as_boolean(), "((int64_t) 1) is true"); -#endif - } - - return done_testing(); -} From f2c49a69baca657e963e3abd314f7f300fb90cc3 Mon Sep 17 00:00:00 2001 From: Otger Date: Sun, 29 Nov 2015 21:11:38 +0100 Subject: [PATCH 69/77] Fixing gcc errors - second attempt --- code/glTFAsset.h | 11 ++++++--- code/glTFAssetWriter.h | 6 +++++ code/glTFAssetWriter.inl | 48 +++++++++++++++++++++++----------------- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/code/glTFAsset.h b/code/glTFAsset.h index 1511d28ea..6f407bf7f 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -754,6 +754,13 @@ namespace glTF virtual void WriteObjects(AssetWriter& writer) = 0; }; + //! (Stub class that is specialized in glTFAssetWriter.h) + template + struct LazyDictWriter + { + static void Write(T& d, AssetWriter& w) {} + }; + //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID //! It is the owner the loaded objects, so when it is destroyed it also deletes them template @@ -774,10 +781,8 @@ namespace glTF void AttachToDocument(Document& doc); void DetachFromDocument(); - void WriteObjectsImpl(AssetWriter& writer); - void WriteObjects(AssetWriter& writer) - { WriteObjectsImpl(writer); } + { LazyDictWriter< LazyDict >::Write(*this, writer); } Ref Add(T* obj); diff --git a/code/glTFAssetWriter.h b/code/glTFAssetWriter.h index 65d05320c..f934288b5 100644 --- a/code/glTFAssetWriter.h +++ b/code/glTFAssetWriter.h @@ -57,6 +57,9 @@ using rapidjson::MemoryPoolAllocator; class AssetWriter { + template + friend struct LazyDictWriter; + private: void WriteBinaryData(IOStream* outfile, size_t sceneLength); @@ -64,6 +67,9 @@ private: void WriteMetadata(); void WriteExtensionsUsed(); + template + void WriteObjects(LazyDict& d); + public: Document mDoc; Asset& mAsset; diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index 174565ef3..1d067809c 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -441,49 +441,57 @@ namespace glTF { mDoc.AddMember("extensionsUsed", exts, mAl); } - template - void LazyDict::WriteObjectsImpl(AssetWriter& w) + void AssetWriter::WriteObjects(LazyDict& d) { - if (mObjs.empty()) return; + if (d.mObjs.empty()) return; - Value* container = &w.mDoc; + Value* container = &mDoc; - if (mExtId) { - Value* exts = FindObject(w.mDoc, "extensions"); + if (d.mExtId) { + Value* exts = FindObject(mDoc, "extensions"); if (!exts) { - w.mDoc.AddMember("extensions", Value().SetObject().Move(), w.mDoc.GetAllocator()); - exts = FindObject(w.mDoc, "extensions"); + mDoc.AddMember("extensions", Value().SetObject().Move(), mDoc.GetAllocator()); + exts = FindObject(mDoc, "extensions"); } - if (!(container = FindObject(*exts, mExtId))) { - exts->AddMember(StringRef(mExtId), Value().SetObject().Move(), w.mDoc.GetAllocator()); - container = FindObject(*exts, mExtId); + if (!(container = FindObject(*exts, d.mExtId))) { + exts->AddMember(StringRef(d.mExtId), Value().SetObject().Move(), mDoc.GetAllocator()); + container = FindObject(*exts, d.mExtId); } } Value* dict; - if (!(dict = FindObject(*container, mDictId))) { - container->AddMember(StringRef(mDictId), Value().SetObject().Move(), w.mDoc.GetAllocator()); - dict = FindObject(*container, mDictId); + if (!(dict = FindObject(*container, d.mDictId))) { + container->AddMember(StringRef(d.mDictId), Value().SetObject().Move(), mDoc.GetAllocator()); + dict = FindObject(*container, d.mDictId); } - for (size_t i = 0; i < mObjs.size(); ++i) { - if (mObjs[i]->IsSpecial()) continue; + for (size_t i = 0; i < d.mObjs.size(); ++i) { + if (d.mObjs[i]->IsSpecial()) continue; Value obj; obj.SetObject(); - if (!mObjs[i]->name.empty()) { - obj.AddMember("name", StringRef(mObjs[i]->name.c_str()), w.mAl); + if (!d.mObjs[i]->name.empty()) { + obj.AddMember("name", StringRef(d.mObjs[i]->name.c_str()), mAl); } - Write(obj, *mObjs[i], w); + Write(obj, *d.mObjs[i], *this); - dict->AddMember(StringRef(mObjs[i]->id), obj, w.mAl); + dict->AddMember(StringRef(d.mObjs[i]->id), obj, mAl); } } + template + struct LazyDictWriter< LazyDict > + { + static void Write(LazyDict& d, AssetWriter& w) + { + w.WriteObjects(d); + } + }; + } From 166ff63af92e2f67bcbacb3414c4d44a651ffd30 Mon Sep 17 00:00:00 2001 From: Otger Date: Sun, 29 Nov 2015 21:20:31 +0100 Subject: [PATCH 70/77] Updated CMAKE - removed removed package inclusion --- code/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index dffb3b474..9eb6ea8c4 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -657,11 +657,6 @@ SET ( openddl_parser_SRCS ) SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS}) -SET( picojson_SRCS - ../contrib/picojson/picojson.h -) -SOURCE_GROUP( picojson FILES ${picojson_SRCS} ) - INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" ) # VC2010 fixes From f896c3329a5aae0ac1c946a29d5cd058426ee426 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 30 Nov 2015 12:52:49 +0100 Subject: [PATCH 71/77] Build: remove deprecated third party lib from cmake --- code/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 69ee3d7c7..94298f0f9 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -655,10 +655,6 @@ SET ( openddl_parser_SRCS ) SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS}) -SET( picojson_SRCS - ../contrib/picojson/picojson.h -) -SOURCE_GROUP( picojson FILES ${picojson_SRCS} ) INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" ) @@ -706,7 +702,6 @@ SET( assimp_src ${Poly2Tri_SRCS} ${Clipper_SRCS} ${openddl_parser_SRCS} - ${picojson_SRCS} # Necessary to show the headers in the project when using the VC++ generator: ${Boost_SRCS} From 1ef84a962f50b6164d37150812432c0a18ee245a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 1 Dec 2015 19:34:54 +0100 Subject: [PATCH 72/77] README: add glTF to readme.md --- Readme.md | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Readme.md b/Readme.md index c051860ac..091e0a09b 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,4 @@ -Open Asset Import Library (assimp) +Open Asset Import Library (assimp) ======== Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. @@ -28,28 +28,28 @@ __Importers__: - BLEND (Blender) - DAE/Collada - FBX -- IFC-STEP +- IFC-STEP - ASE - DXF - HMP - MD2 -- MD3 +- MD3 - MD5 - MDC - MDL - NFF - PLY - STL -- X +- X - OBJ - OpenGEX - SMD -- LWO -- LXO +- LWO +- LXO - LWS -- TER -- AC3D -- MS3D +- TER +- AC3D +- MS3D - COB - Q3BSP - XGL @@ -61,7 +61,8 @@ __Importers__: - Ogre XML - Q3D - ASSBIN (Assimp custom format) - +- glTF + Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default): - C4D (https://github.com/acgessler/assimp-cinema4d) @@ -76,7 +77,8 @@ __Exporters__: - 3DS - JSON (for WebGl, via https://github.com/acgessler/assimp2json) - ASSBIN - +- glTF + ### Building ### @@ -96,7 +98,7 @@ Open Asset Import Library is implemented in C++. The directory structure is: /port Ports to other languages and scripts to maintain those. /test Unit- and regression tests, test suite of models /tools Tools (old assimp viewer, command line `assimp`) - /samples A small number of samples to illustrate possible + /samples A small number of samples to illustrate possible use cases for Assimp /workspaces Build enviroments for vc,xcode,... (deprecated, CMake has superseeded all legacy build options!) @@ -111,23 +113,23 @@ For more information, visit [our website](http://assimp.sourceforge.net/). Or ch If the docs don't solve your problem, ask on [StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github. For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_ - [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) + [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type > /join #assetimporterlib ### Contributing ### -Contributions to assimp are highly appreciated. The easiest way to get involved is to submit +Contributions to assimp are highly appreciated. The easiest way to get involved is to submit a pull request with your changes against the main repository's `master` branch. ### License ### -Our license is based on the modified, __3-clause BSD__-License. +Our license is based on the modified, __3-clause BSD__-License. -An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - +An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp. -For the legal details, see the `LICENSE` file. +For the legal details, see the `LICENSE` file. ### Why this name ### From f8392329380d642243f437600c455a428d6903c4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 2 Dec 2015 14:54:29 +0100 Subject: [PATCH 73/77] Uinittests: add missing license info headers. --- test/unit/utColladaExportCamera.cpp | 42 +++++++++++++++++++--- test/unit/utColladaExportLight.cpp | 42 +++++++++++++++++++--- test/unit/utFastAtof.cpp | 40 +++++++++++++++++++++ test/unit/utFindDegenerates.cpp | 40 +++++++++++++++++++++ test/unit/utFindInvalidData.cpp | 40 +++++++++++++++++++++ test/unit/utFixInfacingNormals.cpp | 40 +++++++++++++++++++++ test/unit/utGenNormals.cpp | 41 +++++++++++++++++++++- test/unit/utImporter.cpp | 40 +++++++++++++++++++++ test/unit/utImproveCacheLocality.cpp | 40 +++++++++++++++++++++ test/unit/utJoinVertices.cpp | 40 +++++++++++++++++++++ test/unit/utLimitBoneWeights.cpp | 40 +++++++++++++++++++++ test/unit/utMaterialSystem.cpp | 40 +++++++++++++++++++++ test/unit/utNoBoostTest.cpp | 40 +++++++++++++++++++++ test/unit/utPretransformVertices.cpp | 44 ++++++++++++++++++++++-- test/unit/utRemoveComments.cpp | 40 +++++++++++++++++++++ test/unit/utRemoveComponent.cpp | 40 +++++++++++++++++++++ test/unit/utRemoveRedundantMaterials.cpp | 40 +++++++++++++++++++++ test/unit/utScenePreprocessor.cpp | 40 +++++++++++++++++++++ test/unit/utSharedPPData.cpp | 40 +++++++++++++++++++++ test/unit/utSortByPType.cpp | 40 +++++++++++++++++++++ test/unit/utSplitLargeMeshes.cpp | 40 +++++++++++++++++++++ test/unit/utTargetAnimation.cpp | 40 +++++++++++++++++++++ test/unit/utTextureTransform.cpp | 40 +++++++++++++++++++++ test/unit/utTriangulate.cpp | 40 +++++++++++++++++++++ test/unit/utVertexTriangleAdjacency.cpp | 40 +++++++++++++++++++++ 25 files changed, 995 insertions(+), 14 deletions(-) diff --git a/test/unit/utColladaExportCamera.cpp b/test/unit/utColladaExportCamera.cpp index 0d864553b..684e545a9 100644 --- a/test/unit/utColladaExportCamera.cpp +++ b/test/unit/utColladaExportCamera.cpp @@ -1,11 +1,43 @@ /* - * ColladaCameraExporter.cpp - * - * Created on: May 17, 2015 - * Author: wise - */ +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- +Copyright (c) 2006-2014, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utColladaExportLight.cpp b/test/unit/utColladaExportLight.cpp index 95c44f7bc..2d6497f2b 100644 --- a/test/unit/utColladaExportLight.cpp +++ b/test/unit/utColladaExportLight.cpp @@ -1,11 +1,43 @@ /* - * ColladaCameraExporter.cpp - * - * Created on: May 17, 2015 - * Author: wise - */ +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- +Copyright (c) 2006-2014, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utFastAtof.cpp b/test/unit/utFastAtof.cpp index 776317431..b95d4da5a 100644 --- a/test/unit/utFastAtof.cpp +++ b/test/unit/utFastAtof.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utFindDegenerates.cpp b/test/unit/utFindDegenerates.cpp index ef85a7bb0..9520a4804 100644 --- a/test/unit/utFindDegenerates.cpp +++ b/test/unit/utFindDegenerates.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utFindInvalidData.cpp b/test/unit/utFindInvalidData.cpp index 9a9bb1ca7..f9741c8ae 100644 --- a/test/unit/utFindInvalidData.cpp +++ b/test/unit/utFindInvalidData.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utFixInfacingNormals.cpp b/test/unit/utFixInfacingNormals.cpp index 21a83a64a..7e2e266b4 100644 --- a/test/unit/utFixInfacingNormals.cpp +++ b/test/unit/utFixInfacingNormals.cpp @@ -1 +1,41 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" diff --git a/test/unit/utGenNormals.cpp b/test/unit/utGenNormals.cpp index be6b5ee8b..8b6414fea 100644 --- a/test/unit/utGenNormals.cpp +++ b/test/unit/utGenNormals.cpp @@ -1,5 +1,44 @@ -#include "UnitTestPCH.h" +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" #include diff --git a/test/unit/utImporter.cpp b/test/unit/utImporter.cpp index 0b300b9b4..1faa9ad70 100644 --- a/test/unit/utImporter.cpp +++ b/test/unit/utImporter.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include "../../include/assimp/postprocess.h" diff --git a/test/unit/utImproveCacheLocality.cpp b/test/unit/utImproveCacheLocality.cpp index 5d0076b61..928be7275 100644 --- a/test/unit/utImproveCacheLocality.cpp +++ b/test/unit/utImproveCacheLocality.cpp @@ -1,2 +1,42 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" \ No newline at end of file diff --git a/test/unit/utJoinVertices.cpp b/test/unit/utJoinVertices.cpp index 1e7c3d08e..cbc68cf92 100644 --- a/test/unit/utJoinVertices.cpp +++ b/test/unit/utJoinVertices.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utLimitBoneWeights.cpp b/test/unit/utLimitBoneWeights.cpp index dfcb037b0..716aecec4 100644 --- a/test/unit/utLimitBoneWeights.cpp +++ b/test/unit/utLimitBoneWeights.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utMaterialSystem.cpp b/test/unit/utMaterialSystem.cpp index 836adcd75..c63469929 100644 --- a/test/unit/utMaterialSystem.cpp +++ b/test/unit/utMaterialSystem.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utNoBoostTest.cpp b/test/unit/utNoBoostTest.cpp index d584e05c2..2cf666597 100644 --- a/test/unit/utNoBoostTest.cpp +++ b/test/unit/utNoBoostTest.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include "BoostWorkaround/boost/tuple/tuple.hpp" diff --git a/test/unit/utPretransformVertices.cpp b/test/unit/utPretransformVertices.cpp index 88fdd15af..318478aae 100644 --- a/test/unit/utPretransformVertices.cpp +++ b/test/unit/utPretransformVertices.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include @@ -7,10 +47,8 @@ using namespace std; using namespace Assimp; -class PretransformVerticesTest : public ::testing::Test -{ +class PretransformVerticesTest : public ::testing::Test { public: - virtual void SetUp(); virtual void TearDown(); diff --git a/test/unit/utRemoveComments.cpp b/test/unit/utRemoveComments.cpp index 611658e8a..96570804b 100644 --- a/test/unit/utRemoveComments.cpp +++ b/test/unit/utRemoveComments.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utRemoveComponent.cpp b/test/unit/utRemoveComponent.cpp index c807a918c..cc5dc4add 100644 --- a/test/unit/utRemoveComponent.cpp +++ b/test/unit/utRemoveComponent.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utRemoveRedundantMaterials.cpp b/test/unit/utRemoveRedundantMaterials.cpp index 769308246..0b2382261 100644 --- a/test/unit/utRemoveRedundantMaterials.cpp +++ b/test/unit/utRemoveRedundantMaterials.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utScenePreprocessor.cpp b/test/unit/utScenePreprocessor.cpp index 3115d3335..c60c07ffa 100644 --- a/test/unit/utScenePreprocessor.cpp +++ b/test/unit/utScenePreprocessor.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utSharedPPData.cpp b/test/unit/utSharedPPData.cpp index cf4f9fcc8..07c137287 100644 --- a/test/unit/utSharedPPData.cpp +++ b/test/unit/utSharedPPData.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utSortByPType.cpp b/test/unit/utSortByPType.cpp index c412905ec..cefda1c63 100644 --- a/test/unit/utSortByPType.cpp +++ b/test/unit/utSortByPType.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utSplitLargeMeshes.cpp b/test/unit/utSplitLargeMeshes.cpp index e116d7f1f..02a8fe556 100644 --- a/test/unit/utSplitLargeMeshes.cpp +++ b/test/unit/utSplitLargeMeshes.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utTargetAnimation.cpp b/test/unit/utTargetAnimation.cpp index 1f799a276..7d797770e 100644 --- a/test/unit/utTargetAnimation.cpp +++ b/test/unit/utTargetAnimation.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" // TODO diff --git a/test/unit/utTextureTransform.cpp b/test/unit/utTextureTransform.cpp index 1f799a276..7d797770e 100644 --- a/test/unit/utTextureTransform.cpp +++ b/test/unit/utTextureTransform.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" // TODO diff --git a/test/unit/utTriangulate.cpp b/test/unit/utTriangulate.cpp index a8dfa5b8c..adffe687a 100644 --- a/test/unit/utTriangulate.cpp +++ b/test/unit/utTriangulate.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include diff --git a/test/unit/utVertexTriangleAdjacency.cpp b/test/unit/utVertexTriangleAdjacency.cpp index befa937cf..2629d67aa 100644 --- a/test/unit/utVertexTriangleAdjacency.cpp +++ b/test/unit/utVertexTriangleAdjacency.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2014, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "UnitTestPCH.h" #include "assimp/types.h" From 87369070092b9b679f7548b911f1cd32aa3b9861 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 2 Dec 2015 19:58:43 +0100 Subject: [PATCH 74/77] Importer: fix overflowImporter: fix overflow. --- code/Importer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/Importer.cpp b/code/Importer.cpp index aa0b51a93..14b5c096c 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -503,7 +503,8 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength)); // read the file and recover the previous IOSystem - char fbuff[128]; + static const size_t BufferSize(Importer::MaxLenHint + 28); + char fbuff[ BufferSize ]; sprintf(fbuff,"%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint); ReadFile(fbuff,pFlags); From 6641188a8edefcf52bb702a700ef56df78044f57 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 6 Dec 2015 12:18:33 +0100 Subject: [PATCH 75/77] assimp/issues/702: fix resource leak and use initializer list for all attributes of the loader instance. --- code/ColladaParser.cpp | 45 ++++++++++++++++++++++++++++------------ code/DefaultIOSystem.cpp | 1 - code/OpenGEXImporter.cpp | 13 ++++++++++++ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index b239dbe88..2ce7cad23 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -65,27 +65,46 @@ using namespace Assimp::Collada; // Constructor to be privately used by Importer ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile) : mFileName( pFile) + , mReader( NULL ) + , mDataLibrary() + , mAccessorLibrary() + , mMeshLibrary() + , mNodeLibrary() + , mImageLibrary() + , mEffectLibrary() + , mMaterialLibrary() + , mLightLibrary() + , mCameraLibrary() + , mControllerLibrary() + , mRootNode( NULL ) + , mAnims() + , mUnitSize( 1.0f ) + , mUpDirection( UP_Y ) + , mFormat(FV_1_5_n ) // We assume the newest file format by default { - mRootNode = NULL; - mUnitSize = 1.0f; - mUpDirection = UP_Y; + // Validate io-handler instance + if ( NULL == pIOHandler ) { + throw DeadlyImportError("IOSystem is NULL." ); + } - // We assume the newest file format by default - mFormat = FV_1_5_n; - - // open the file - boost::scoped_ptr file( pIOHandler->Open( pFile)); - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open file " + pFile + "."); + // open the file + boost::scoped_ptr file( pIOHandler->Open( pFile ) ); + if ( file.get() == NULL ) { + throw DeadlyImportError( "Failed to open file " + pFile + "." ); + } // generate a XML reader for it - boost::scoped_ptr mIOWrapper( new CIrrXML_IOStreamReader( file.get())); + boost::scoped_ptr mIOWrapper( new CIrrXML_IOStreamReader( file.get())); mReader = irr::io::createIrrXMLReader( mIOWrapper.get()); - if( !mReader) - ThrowException( "Collada: Unable to open file."); + if (!mReader) { + ThrowException("Collada: Unable to open file."); + } // start reading ReadContents(); + + // Release file after import + pIOHandler->Close( file.get() ); } // ------------------------------------------------------------------------------------------------ diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 89d40e2a5..83380df5b 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -176,7 +176,6 @@ std::string DefaultIOSystem::fileName( const std::string &path ) return ret; } - // ------------------------------------------------------------------------------------------------ std::string DefaultIOSystem::completeBaseName( const std::string &path ) { diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index f260cc772..ab702b717 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -801,6 +801,19 @@ void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScen } } +//------------------------------------------------------------------------------------------------ +bool isSpecialRootDir(aiString &texName) { + if (texName.length < 2) { + return false; + } + + if (texName.data[0] = '/' || texName.data[1] == '/') { + return true; + } + + return false; +} + //------------------------------------------------------------------------------------------------ void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene ) { if( NULL == node ) { From f5e13874e088543aca4cc3ffc1f5b0680b6d10b5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 6 Dec 2015 16:49:10 +0100 Subject: [PATCH 76/77] glTF: check if exporter option has broke someting. --- code/Exporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 215fa671c..5e5f2711a 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -139,9 +139,9 @@ Exporter::ExportFormatEntry gExporters[] = #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF, - aiProcess_JoinIdenticalVertices | aiProcess_SortByPType), + aiProcess_JoinIdenticalVertices /*| aiProcess_SortByPType*/), Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, - aiProcess_JoinIdenticalVertices | aiProcess_SortByPType), + aiProcess_JoinIdenticalVertices /*| aiProcess_SortByPType*/), #endif #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER From 0a6788d56ff8b6def164473864b0df6f997d61ad Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 7 Dec 2015 20:43:01 +0100 Subject: [PATCH 77/77] try to fix build. --- code/ColladaParser.cpp | 8 ++-- test/regression/run.py | 98 ++++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 2ce7cad23..8eeaddba9 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -64,7 +64,7 @@ using namespace Assimp::Collada; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile) - : mFileName( pFile) + : mFileName( pFile ) , mReader( NULL ) , mDataLibrary() , mAccessorLibrary() @@ -82,7 +82,7 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile) , mUpDirection( UP_Y ) , mFormat(FV_1_5_n ) // We assume the newest file format by default { - // Validate io-handler instance + // validate io-handler instance if ( NULL == pIOHandler ) { throw DeadlyImportError("IOSystem is NULL." ); } @@ -103,8 +103,8 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile) // start reading ReadContents(); - // Release file after import - pIOHandler->Close( file.get() ); + // release file after import + //pIOHandler->Close( file.get() ); } // ------------------------------------------------------------------------------------------------ diff --git a/test/regression/run.py b/test/regression/run.py index 4763ad9d3..66b259903 100755 --- a/test/regression/run.py +++ b/test/regression/run.py @@ -9,34 +9,34 @@ # # All rights reserved. # -# Redistribution and use of this software in source and binary forms, -# with or without modification, are permitted provided that the following +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the following # conditions are met: -# +# # * Redistributions of source code must retain the above # copyright notice, this list of conditions and the # following disclaimer. -# +# # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the # following disclaimer in the documentation and/or other # materials provided with the distribution. -# +# # * Neither the name of the ASSIMP team, nor the names of its # contributors may be used to endorse or promote products # derived from this software without specific prior # written permission of the ASSIMP Development Team. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # --------------------------------------------------------------------------- @@ -98,7 +98,7 @@ outfilename_output = "run_regression_suite_output.txt" outfilename_failur = "run_regression_suite_failures.csv" # ------------------------------------------------------------------------------- class results: - + """ Handle formatting of results""" def __init__(self, zipin): @@ -106,15 +106,15 @@ class results: self.failures = [] self.success = [] self.zipin = zipin - - + + def fail(self, failfile, filename_expect, pp, msg, *args): """ Report failure of a sub-test - - File f failed a test for pp config pp, failure notice is msg, + + File f failed a test for pp config pp, failure notice is msg, *args is format()ting args for msg - + """ print("[FAILURE] " + messages[msg].format(*args)) self.failures.append((failfile, filename_expect, pp)) @@ -124,11 +124,11 @@ class results: """ Report success of a sub-test - File f passed the test, msg is a happy success note, + File f passed the test, msg is a happy success note, *args is format()ing args for msg. """ - print("[SUCCESS] " + messages[msg].format(*args)) + print("[SUCCESS] " + messages[msg].format(*args)) self.success.append(f) @@ -139,22 +139,22 @@ class results: count_fail = len(self.failures) percent_good = float(count_success) / (count_success + count_fail) print("\n" + ('='*60) + "\n" + "SUCCESS: {0}\nFAILURE: {1}\nPercentage good: {2}".format( - count_success, count_fail, percent_good) + + count_success, count_fail, percent_good) + "\n" + ('='*60) + "\n") with open(os.path.join('..', 'results',outfilename_failur), "wt") as f: f.write("ORIGINAL FILE;EXPECTED DUMP\n") f.writelines(map( lambda x: x[0] + ' ' + x[2] + ";" + x[1] + "\n", self.failures)) - + if self.failures: - print("\nSee " + settings.results + "\\" + outfilename_failur - + " for more details\n\n") - + print("\nSee " + settings.results + "\\" + outfilename_failur + + " for more details\n\n") + def hasFailures( self ): """ Return True, if any failures there. """ return 0 != len( self.failures ) - + # ------------------------------------------------------------------------------- def prepare_output_dir(fullpath, myhash, app): outfile = os.path.join(settings.results, "tmp", os.path.split(fullpath)[1] + "_" + myhash) @@ -162,7 +162,7 @@ def prepare_output_dir(fullpath, myhash, app): os.mkdir(outfile) except OSError: pass - + outfile = os.path.join(outfile, app) return outfile @@ -197,8 +197,8 @@ def process_dir(d, outfile_results, zipin, result): "regression database? Use gen_db.zip to re-generate.") continue - print("-"*60 + "\n " + os.path.realpath(fullpath) + " pp: " + pppreset) - + print("-"*60 + "\n " + os.path.realpath(fullpath) + " pp: " + pppreset) + outfile_actual = prepare_output_dir(fullpath, filehash, "ACTUAL") outfile_expect = prepare_output_dir(fullpath, filehash, "EXPECT") outfile_results.write("assimp dump "+"-"*80+"\n") @@ -219,19 +219,19 @@ def process_dir(d, outfile_results, zipin, result): outfile_results.write("Expected import to fail\n") continue elif failure and r: - result.ok(fullpath, pppreset, EXPECTED_FAILURE) + result.ok(fullpath, pppreset, EXPECTED_FAILURE) outfile_results.write("Failed as expected, skipping.\n") continue - - with open(outfile_expect, "wb") as s: - s.write(input_expected) - try: + with open(outfile_expect, "wb") as s: + s.write(input_expected) + + try: with open(outfile_actual, "rb") as s: - input_actual = s.read() + input_actual = s.read() except IOError: continue - + outfile_results.write("Expected data length: {0}\n".format(len(input_expected))) outfile_results.write("Actual data length: {0}\n".format(len(input_actual))) failed = False @@ -247,9 +247,9 @@ def process_dir(d, outfile_results, zipin, result): if subprocess.call(command, **shellparams) != 0: if not failed: result.fail(fullpath, outfile_expect, pppreset, DATABASE_VALUE_MISMATCH) - continue - - result.ok(fullpath, pppreset, COMPARE_SUCCESS, len(input_expected)) + continue + + result.ok(fullpath, pppreset, COMPARE_SUCCESS, len(input_expected)) # ------------------------------------------------------------------------------- def del_folder_with_contents(folder): @@ -258,13 +258,14 @@ def del_folder_with_contents(folder): os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) - + # ------------------------------------------------------------------------------- def run_test(): tmp_target_path = os.path.join(settings.results, "tmp") - try: - os.mkdir(tmp_target_path) + try: + print "try to make " + tmp_target_path + os.mkdir(tmp_target_path) except OSError as oerr: # clear contents if tmp folder exists already del_folder_with_contents(tmp_target_path) @@ -272,7 +273,7 @@ def run_test(): try: zipin = zipfile.ZipFile(settings.database_name + ".zip", "r", zipfile.ZIP_STORED) - + except IOError: print("Regression database ", settings.database_name, ".zip was not found") @@ -286,13 +287,16 @@ def run_test(): res.report_results() if res.hasFailures(): return 1 - + return 0 - + # ------------------------------------------------------------------------------- if __name__ == "__main__": - assimp_bin_path = sys.argv[1] if len(sys.argv) > 1 else 'assimp' + if len(sys.argv) > 1: + assimp_bin_path = sys.argv[1] + else: + assimp_bin_path = 'assimp' print('Using assimp binary: ' + assimp_bin_path) sys.exit( run_test() )

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 E0O)`BRsaA1 delta 154818 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 N*LtuhJPJN<{|7VQCS(8r From a51d9a3884481bc8fcf9ade05b28a7ceeaa49fb1 Mon Sep 17 00:00:00 2001 From: Otger Date: Tue, 24 Nov 2015 17:51:11 +0100 Subject: [PATCH 56/77] Ignore FBX 'PP' type connections (they were stopping the file parsing) --- code/FBXDocument.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index d934c9754..52f4c81bd 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -486,6 +486,11 @@ void Document::ReadConnections() for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) { const Element& el = *(*it).second; const std::string& type = ParseTokenAsString(GetRequiredToken(el,0)); + + // PP = property-property connection, ignored for now + // (tokens: "PP", ID1, "Property1", ID2, "Property2") + if(type == "PP") continue; + const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1)); const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2)); From db8845d2b21eae7f86683336266cad179787d89c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 25 Nov 2015 22:03:39 +0100 Subject: [PATCH 57/77] glTF: add jsn reader + example model to work on. --- code/CMakeLists.txt | 11 + code/glTFImporter.cpp | 24 +- code/glTFImporter.h | 6 +- contrib/picojson/.gitignore | 4 + contrib/picojson/.gitmodules | 0 contrib/picojson/.travis.yml | 8 + contrib/picojson/Changes | 25 + contrib/picojson/LICENSE | 25 + contrib/picojson/Makefile | 26 + contrib/picojson/README.mkdn | 195 ++++ contrib/picojson/examples/github-issues.cc | 110 ++ contrib/picojson/examples/iostream.cc | 70 ++ contrib/picojson/examples/streaming.cc | 76 ++ contrib/picojson/picojson.h | 1039 +++++++++++++++++ contrib/picojson/picotest/picotest.c | 99 ++ contrib/picojson/picotest/picotest.h | 39 + contrib/picojson/test.cc | 325 ++++++ .../glTF/CesiumMilkTruck/CesiumMilkTruck.bin | Bin 0 -> 113052 bytes .../glTF/CesiumMilkTruck/CesiumMilkTruck.gltf | 705 +++++++++++ .../glTF/CesiumMilkTruck/CesiumMilkTruck.png | Bin 0 -> 923282 bytes .../CesiumMilkTruck/CesiumMilkTruck0FS.glsl | 17 + .../CesiumMilkTruck/CesiumMilkTruck0VS.glsl | 12 + .../CesiumMilkTruck/CesiumMilkTruck1FS.glsl | 18 + .../CesiumMilkTruck/CesiumMilkTruck1VS.glsl | 15 + 24 files changed, 2846 insertions(+), 3 deletions(-) create mode 100644 contrib/picojson/.gitignore create mode 100644 contrib/picojson/.gitmodules create mode 100644 contrib/picojson/.travis.yml create mode 100644 contrib/picojson/Changes create mode 100644 contrib/picojson/LICENSE create mode 100644 contrib/picojson/Makefile create mode 100644 contrib/picojson/README.mkdn create mode 100644 contrib/picojson/examples/github-issues.cc create mode 100644 contrib/picojson/examples/iostream.cc create mode 100644 contrib/picojson/examples/streaming.cc create mode 100644 contrib/picojson/picojson.h create mode 100644 contrib/picojson/picotest/picotest.c create mode 100644 contrib/picojson/picotest/picotest.h create mode 100644 contrib/picojson/test.cc create mode 100644 test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.bin create mode 100644 test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.gltf create mode 100644 test/models/glTF/CesiumMilkTruck/CesiumMilkTruck.png create mode 100644 test/models/glTF/CesiumMilkTruck/CesiumMilkTruck0FS.glsl create mode 100644 test/models/glTF/CesiumMilkTruck/CesiumMilkTruck0VS.glsl create mode 100644 test/models/glTF/CesiumMilkTruck/CesiumMilkTruck1FS.glsl create mode 100644 test/models/glTF/CesiumMilkTruck/CesiumMilkTruck1VS.glsl diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 2b7bcec7b..33de95cb6 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -562,6 +562,11 @@ ADD_ASSIMP_IMPORTER(X XFileExporter.cpp ) +ADD_ASSIMP_IMPORTER( glFT + glTFImporter.cpp + glTFImporter.h +) + SET( Step_SRCS StepExporter.h StepExporter.cpp @@ -644,6 +649,11 @@ SET ( openddl_parser_SRCS ) SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS}) +SET( picojson_SRCS + ../contrib/picojson/picojson.h +) +SOURCE_GROUP( picojson FILES ${picojson_SRCS} ) + # VC2010 fixes if(MSVC10) option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF ) @@ -688,6 +698,7 @@ SET( assimp_src ${Poly2Tri_SRCS} ${Clipper_SRCS} ${openddl_parser_SRCS} + ${picojson_SRCS} # Necessary to show the headers in the project when using the VC++ generator: ${Boost_SRCS} diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index ece3ec19c..82c5c798a 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -38,6 +38,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ #include "glTFImporter.h" +#include "StreamReader.h" +#include "DefaultIOSystem.h" + +#include +#include +#include +#include +#include + +#include "../contrib/picojson/picojson.h" namespace Assimp { @@ -55,7 +65,9 @@ namespace Assimp { }; glTFImporter::glTFImporter() -: BaseImporter() { +: BaseImporter() +, m_scene( NULL ) +, m_buffer() { } @@ -72,7 +84,17 @@ const aiImporterDesc* glTFImporter::GetInfo() const { } void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) { + m_scene = pScene; + boost::shared_ptr stream( pIOHandler->Open( pFile, "rb" ) ); + if (!stream.get()) { + throw DeadlyImportError( "Failed to open file " + pFile + "." ); + } + // Get the file-size and validate it, throwing an exception when fails + size_t fileSize = stream->FileSize(); + + // Allocate buffer and read file into it + TextFileToBuffer( stream.get(), m_buffer ); } } diff --git a/code/glTFImporter.h b/code/glTFImporter.h index dc13c8a17..10033649b 100644 --- a/code/glTFImporter.h +++ b/code/glTFImporter.h @@ -52,8 +52,10 @@ public: protected: virtual const aiImporterDesc* GetInfo() const; - virtual void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler ); + virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ); + +private: + aiScene *m_scene; }; } // Namespace assimp diff --git a/contrib/picojson/.gitignore b/contrib/picojson/.gitignore new file mode 100644 index 000000000..815b59fad --- /dev/null +++ b/contrib/picojson/.gitignore @@ -0,0 +1,4 @@ +*~ +a.out +test-core +test-core-int64 diff --git a/contrib/picojson/.gitmodules b/contrib/picojson/.gitmodules new file mode 100644 index 000000000..e69de29bb diff --git a/contrib/picojson/.travis.yml b/contrib/picojson/.travis.yml new file mode 100644 index 000000000..e2af2ae62 --- /dev/null +++ b/contrib/picojson/.travis.yml @@ -0,0 +1,8 @@ +language: cpp + +compiler: + - clang + - gcc + +script: + - make test diff --git a/contrib/picojson/Changes b/contrib/picojson/Changes new file mode 100644 index 000000000..d6017ddf9 --- /dev/null +++ b/contrib/picojson/Changes @@ -0,0 +1,25 @@ +Revision history for picojson + +1.3.0 2015-02-25 13:05:00+0900 + - `make check` is now synonym of `make test` (#62) + - operator= is now safe when part of LHS is being assigned, as well as exception-safe (#66) + +1.2.1 2014-12-16 15:33:00+0900 + - bundle the contents of `picotest/` (#61) + +1.2.0 2014-12-15 16:20:00+0900 + - `make install` to install picojson.h (#58) + - two-argument `picojson::parse()` for ease-of-use (#57) + +1.1.1 2014-06-25 10:35:00+0900 + - tweaks to suppress compiler errors / warning (#38 #39) + - clarify the licenses of the files in exmaple/ (#42) + +1.1 2014-06-16 12:57:00+0900 + - added experimental support for int64 type (#34) + - by default, throw std::runtime_error instead of using assert for runtime errors (#33) + - refine compatibility regarding the use of isinf/isnan (#29, #36) + - remove `.get()` (#35) + +1.0 2014-06-05 12:54:00+0900 + - initial release with a version number diff --git a/contrib/picojson/LICENSE b/contrib/picojson/LICENSE new file mode 100644 index 000000000..72f355391 --- /dev/null +++ b/contrib/picojson/LICENSE @@ -0,0 +1,25 @@ +Copyright 2009-2010 Cybozu Labs, Inc. +Copyright 2011-2014 Kazuho Oku +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/picojson/Makefile b/contrib/picojson/Makefile new file mode 100644 index 000000000..908e2a0a0 --- /dev/null +++ b/contrib/picojson/Makefile @@ -0,0 +1,26 @@ +prefix=/usr/local +includedir=$(prefix)/include + +check: test + +test: test-core test-core-int64 + ./test-core + ./test-core-int64 + +test-core: picojson.h test.cc picotest/picotest.c picotest/picotest.h + $(CXX) -Wall test.cc picotest/picotest.c -o $@ + +test-core-int64: picojson.h test.cc picotest/picotest.c picotest/picotest.h + $(CXX) -Wall -DPICOJSON_USE_INT64 test.cc picotest/picotest.c -o $@ + +clean: + rm -f test-core test-core-int64 + +install: + install -d $(DESTDIR)$(includedir) + install -p -m 0644 picojson.h $(DESTDIR)$(includedir) + +uninstall: + rm -f $(DESTDIR)$(includedir)/picojson.h + +.PHONY: test check clean install uninstall diff --git a/contrib/picojson/README.mkdn b/contrib/picojson/README.mkdn new file mode 100644 index 000000000..b59fc76c3 --- /dev/null +++ b/contrib/picojson/README.mkdn @@ -0,0 +1,195 @@ +# PicoJSON - a C++ JSON parser / serializer + +Copyright © 2009-2010 Cybozu Labs, Inc. +Copyright © 2011-2015 Kazuho Oku + +Licensed under [2-clause BSD license](http://opensource.org/licenses/BSD-2-Clause) + +## Version + +1.3.1-dev [![Build Status](https://travis-ci.org/kazuho/picojson.svg?branch=master)](https://travis-ci.org/kazuho/picojson) + +## Introduction + +PicoJSON is a tiny JSON parser / serializer for C++ with following properties: + +- header-file only +- no external dependencies (only uses standard C++ libraries) +- STL-frendly (arrays are represented by using std::vector, objects are std::map) +- provides both pull interface and streaming (event-based) interface + +## Reading JSON using the pull interface + +There are several ways to use the pull (DOM-like) interface of picojson. + +The easiest way is to use the two-argument `parse` function. + +``` +std::string json = "[ \"hello JSON\" ]"; +picojson::value v; +std::string err = picojson::parse(v, json); +if (! err.empty()) { + std:cerr << err << std::endl; +} +``` + +Four-argument `parse` function accepts a pair of iterators, and returns the end position of the input. + +``` +const char* json = "{\"a\":1}"; +picojson::value v; +std::string err; +const char* json_end = picojson::parse(v, json, json + strlen(json), &err); +if (! err.empty()) { + std::cerr << err << std::endl; +} +``` + +``` +std::istream_iterator input(std::cin); +picojson::value v; +std::string err; +input = picojson::parse(v, input, std::istream_iterator(), &err); +if (! err.empty()) { + std::cerr << err << std::endl; +} +``` + +It is also possible to use the `>>` operator to parse the input, however this interface is not thread-safe. + +``` +picosjon::value v; +std::cin >> v; +std::string err = picojson::get_last_error(); +``` + +## Accessing the values + +Values of a JSON object is represented as instances of picojson::value class. + +