diff --git a/CMakeLists.txt b/CMakeLists.txt index 18901f0..7d92172 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,15 +11,6 @@ endif () string (TOLOWER ${CMAKE_BUILD_TYPE} glTF_BUILD_TYPE) -if ( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" ) - set (CASABLANCA_LIBRARY libcpprest.2.4.${LIBRARY_EXT}) -elseif ( UNIX ) - set (CASABLANCA_LIBRARY libcpprest.${LIBRARY_EXT}) -else () - set (CASABLANCA_LIBRARY libcpprest.2.4.${LIBRARY_EXT}) -endif () -message (STATUS "Using Casablanca: " ${CASABLANCA}) - set (FBX_SDK_INCLUDES ${FBX_SDK}/include) if ( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" ) set (FBX_SDK_LIBS ${FBX_SDK}/lib/clang/${glTF_BUILD_TYPE}) @@ -46,7 +37,6 @@ if ( WIN32 ) # Check if we are on Windows add_definitions (-DUNICODE -D_WIN64 -D_GLTF_EXPORTS_ -D_WINDOWS -D_USRDLL) elseif ( UNIX ) # This includes OSX option (BUILD_SHARED_LIBS "Build shared Libraries." ON) - find_package (Boost REQUIRED COMPONENTS random chrono system thread locale regex filesystem) else () message (FATAL_ERROR "-- Unsupported Build Platform.") endif () @@ -54,11 +44,11 @@ endif () # Compiler (not platform) specific settings if ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) message ("-- Setting clang options") - + set (WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls") set (OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder") set (WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}") - + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") set (CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") set (CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11") @@ -66,7 +56,7 @@ if ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") elseif ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" ) message ("-- Setting gcc options") - + set (WARNINGS "-Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code") set (LINUX_SUPPRESSIONS "-Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-unused-function -Wno-char-subscripts -Wno-switch -Wno-unused-but-set-parameter -Wno-unused-value -Wno-unused-local-typedefs") @@ -74,12 +64,12 @@ elseif ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" ) set (LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") - set (LD_LIBRARY_PATH ${CASABLANCA_LIBS}) else () message ("-- Unknown compiler, success is doubtful.") endif () +add_subdirectory (jsoncpp) add_subdirectory (IO-glTF) add_subdirectory (glTF) diff --git a/IO-glTF/CMakeLists.txt b/IO-glTF/CMakeLists.txt index eb039f5..d2a3e98 100644 --- a/IO-glTF/CMakeLists.txt +++ b/IO-glTF/CMakeLists.txt @@ -7,6 +7,7 @@ set (IOGLTF_VERSION ${IOGLTF_MAJOR_VERSION}.${IOGLTF_MINOR_VERSION}.${IOGLTF_PAT # IO-glTF dynamic libray file (GLOB_RECURSE IO-glTF-src ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) include_directories ( + ../ ${FBX_SDK_INCLUDES} /usr/local/include ) @@ -17,9 +18,8 @@ link_directories ( add_library (IO-glTF SHARED ${IO-glTF-src}) target_link_libraries ( IO-glTF + jsoncpp ${FBX_SDK_LIBRARY} - ${CASABLANCA_LIBRARY} - ${Boost_LIBRARIES} ${Boost_FRAMEWORK} ) # Support Files diff --git a/IO-glTF/IOglTF.cpp b/IO-glTF/IOglTF.cpp index 68a0200..d8c2319 100644 --- a/IO-glTF/IOglTF.cpp +++ b/IO-glTF/IOglTF.cpp @@ -93,23 +93,23 @@ bool IOglTF::SpecificInitialize () { /*static*/ const unsigned int IOglTF::FRAGMENT_SHADER ; /*static*/ const unsigned int IOglTF::VERTEX_SHADER ; #endif -/*static*/ const utility::char_t *IOglTF::szSCALAR =U("SCALAR") ; -/*static*/ const utility::char_t *IOglTF::szFLOAT =U("FLOAT") ; -/*static*/ const utility::char_t *IOglTF::szVEC2 =U("VEC2") ; -/*static*/ const utility::char_t *IOglTF::szVEC3 =U("VEC3") ; -/*static*/ const utility::char_t *IOglTF::szVEC4 =U ("VEC4") ; -/*static*/ const utility::char_t *IOglTF::szINT =U("INT") ; ; -/*static*/ const utility::char_t *IOglTF::szIVEC2 =U("IVEC2") ; ; -/*static*/ const utility::char_t *IOglTF::szIVEC3 =U("IVEC3") ; ; -/*static*/ const utility::char_t *IOglTF::szIVEC4 =U("IVEC4") ; ; -/*static*/ const utility::char_t *IOglTF::szBOOL =U("BOOL") ; ; -/*static*/ const utility::char_t *IOglTF::szBVEC2 =U("BVEC2") ; ; -/*static*/ const utility::char_t *IOglTF::szBVEC3 =U("BVEC3") ; ; -/*static*/ const utility::char_t *IOglTF::szBVEC4 =U("BVEC4") ; ; -/*static*/ const utility::char_t *IOglTF::szMAT2 =U("MAT2") ; -/*static*/ const utility::char_t *IOglTF::szMAT3 =U("MAT3") ; -/*static*/ const utility::char_t *IOglTF::szMAT4 =U("MAT4") ; -/*static*/ const utility::char_t *IOglTF::szSAMPLER_2D =U("sampler2D") ; +/*static*/ const char *IOglTF::szSCALAR =("SCALAR") ; +/*static*/ const char *IOglTF::szFLOAT =("FLOAT") ; +/*static*/ const char *IOglTF::szVEC2 =("VEC2") ; +/*static*/ const char *IOglTF::szVEC3 =("VEC3") ; +/*static*/ const char *IOglTF::szVEC4 =("VEC4") ; +/*static*/ const char *IOglTF::szINT =("INT") ; ; +/*static*/ const char *IOglTF::szIVEC2 =("IVEC2") ; ; +/*static*/ const char *IOglTF::szIVEC3 =("IVEC3") ; ; +/*static*/ const char *IOglTF::szIVEC4 =("IVEC4") ; ; +/*static*/ const char *IOglTF::szBOOL =("BOOL") ; ; +/*static*/ const char *IOglTF::szBVEC2 =("BVEC2") ; ; +/*static*/ const char *IOglTF::szBVEC3 =("BVEC3") ; ; +/*static*/ const char *IOglTF::szBVEC4 =("BVEC4") ; ; +/*static*/ const char *IOglTF::szMAT2 =("MAT2") ; +/*static*/ const char *IOglTF::szMAT3 =("MAT3") ; +/*static*/ const char *IOglTF::szMAT4 =("MAT4") ; +/*static*/ const char *IOglTF::szSAMPLER_2D =("sampler2D") ; #ifdef __APPLE__ /*static*/ const unsigned int IOglTF::ARRAY_BUFFER ; /*static*/ const unsigned int IOglTF::ELEMENT_ARRAY_BUFFER ; @@ -142,9 +142,9 @@ bool IOglTF::SpecificInitialize () { /*static*/ const unsigned int IOglTF::MIRRORED_REPEAT ; /*static*/ const unsigned int IOglTF::REPEAT ; #endif -/*static*/ const web::json::value IOglTF::Identity2 =web::json::value::array ({ { 1., 0., 0., 1. } }) ; -/*static*/ const web::json::value IOglTF::Identity3 =web::json::value::array ({ { 1., 0., 0., 0., 1., 0., 0., 0., 1. } }) ; -/*static*/ const web::json::value IOglTF::Identity4 =web::json::value::array ({{ 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. }}) ; +/*static*/ const Json::Value IOglTF::Identity2 ;//=Json::Value::array ({ { 1., 0., 0., 1. } }) ; +/*static*/ const Json::Value IOglTF::Identity3 ;// =Json::Value::array ({ { 1., 0., 0., 0., 1., 0., 0., 0., 1. } }) ; +/*static*/ const Json::Value IOglTF::Identity4 ;// =Json::Value::array ({{ 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. }}) ; // Get extension, description or version info about gltfWriter void *_gltfFormatInfo (FbxWriter::EInfoRequest pRequest, int pId) { @@ -171,8 +171,8 @@ void *_gltfFormatInfo (FbxWriter::EInfoRequest pRequest, int pId) { } //----------------------------------------------------------------------------- -/*static*/ unsigned int IOglTF::techniqueParameters (const utility::char_t *szType, int compType /*=FLOAT*/) { - utility::string_t st (szType) ; +/*static*/ unsigned int IOglTF::techniqueParameters (const char *szType, int compType /*=FLOAT*/) { + std::string st (szType) ; if ( st == szSCALAR ) return (compType) ; if ( st == szVEC2 ) @@ -190,7 +190,7 @@ void *_gltfFormatInfo (FbxWriter::EInfoRequest pRequest, int pId) { return (0) ; } -/*static*/ const utility::char_t *IOglTF::glslAccessorType (unsigned int glType) { +/*static*/ const char *IOglTF::glslAccessorType (unsigned int glType) { switch ( glType ) { case FLOAT: case INT: @@ -219,11 +219,11 @@ void *_gltfFormatInfo (FbxWriter::EInfoRequest pRequest, int pId) { case FLOAT_MAT4: return (szMAT4) ; } - return (U("")) ; + return (("")) ; } -/*static*/ const utility::string_t IOglTF::glslShaderType (unsigned int glType) { - utility::string_t szType ; +/*static*/ const std::string IOglTF::glslShaderType (unsigned int glType) { + std::string szType ; switch ( glType ) { case FLOAT: szType =szFLOAT ; @@ -268,54 +268,126 @@ void *_gltfFormatInfo (FbxWriter::EInfoRequest pRequest, int pId) { return (szType) ; } -/*static*/ const utility::char_t *IOglTF::mimeType (const utility::char_t *szFilename) { - utility::string_t contentType =U("application/octet-stream") ; - FbxString ext =FbxPathUtils::GetExtensionName (utility::conversions::to_utf8string (szFilename).c_str ()) ; +/*static*/ const char *IOglTF::mimeType (const char *szFilename) { + std::string contentType =("application/octet-stream") ; + FbxString ext =FbxPathUtils::GetExtensionName (szFilename) ; ext =ext.Lower () ; if ( ext == "png" ) - return (U("image/png")) ; + return (("image/png")) ; if ( ext == "gif" ) - return (U("image/gif")) ; + return (("image/gif")) ; if ( ext == "jpg" || ext == "jpeg" ) - return (U("image/jpeg")) ; - return (U("application/octet-stream")) ; + return (("image/jpeg")) ; + return (("application/octet-stream")) ; } + +/* +base64.cpp and base64.h -/*static*/ const utility::string_t IOglTF::dataURI (const utility::string_t fileName) { +Copyright (C) 2004-2008 RenĂ© Nyffenegger + +This source code is provided 'as-is', without any express or implied +warranty. In no event will the author be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this source code must not be misrepresented; you must not +claim that you wrote the original source code. If you use this source code +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original source code. + +3. This notice may not be removed or altered from any source distribution. + +RenĂ© Nyffenegger rene.nyffenegger@adp-gmbh.ch + +*/ + +static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) + { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while((i++ < 3)) + ret += '='; + + } + + return ret; + +} + +/*static*/ const std::string IOglTF::dataURI (const std::string fileName) { // data:[][;charset=][;base64], - utility::string_t st (U ("data:")) ; - Concurrency::streams::file_stream::open_istream (fileName) - .then ([&] (pplx::task > previousTask) { - try { - auto fileStream =previousTask.get () ; - fileStream.seek (0, std::ios::end) ; - auto length =static_cast (fileStream.tell ()) ; - fileStream.seek (0, std::ios_base::beg) ; - concurrency::streams::streambuf buff (fileStream.streambuf ()) ; + std::string st (("data:")) ; + std::fstream fileStream( fileName ); + + try { + fileStream.seekg (0, std::ios::end) ; + auto length =static_cast (fileStream.tellg ()) ; + fileStream.seekg (0, std::ios_base::beg) ; - std::vector v8 ; - v8.resize (length) ; - buff.seekpos (0, std::ios_base::binary) ; - buff.getn (&v8.front (), length) ; + std::vector v8 ; + v8.resize (length) ; + fileStream.get (reinterpret_cast(v8.data()), length) ; - st +=IOglTF::mimeType (fileName.c_str ()) ; - //st +="[;charset=]" ; - st +=U (";base64") ; - st +=U (",") + utility::conversions::to_base64 (v8) ; - } catch ( ... ) { - //ucout << U("Error: ") << e.what () << std::endl ; - } - }).wait () ; + st +=IOglTF::mimeType (fileName.c_str ()) ; + //st +="[;charset=]" ; + st +=(";base64") ; + st +=(",") + base64_encode( v8.data(), static_cast(length) ) ; + } catch ( ... ) { + //std::cout << ("Error: ") << e.what () << std::endl ; + } return (st) ; } -/*static*/ const utility::string_t IOglTF::dataURI (memoryStream &stream) { +/*static*/ const std::string IOglTF::dataURI (memoryStream &stream) { // data:[][;charset=][;base64], - utility::string_t st (U ("data:")) ; - st +=IOglTF::mimeType (U("")) ; + std::string st (("data:")) ; + st +=IOglTF::mimeType (("")) ; //st +="[;charset=]" ; - st +=U (";base64") ; - st +=U (",") + utility::conversions::to_base64 (stream.vec ()) ; + st +=(";base64") ; + auto &vec = stream.vec(); + st +=(",") + base64_encode( vec.data(), static_cast(vec.size()) ) ; return (st) ; } diff --git a/IO-glTF/IOglTF.h b/IO-glTF/IOglTF.h index 2cd1d91..ae8924c 100644 --- a/IO-glTF/IOglTF.h +++ b/IO-glTF/IOglTF.h @@ -20,6 +20,8 @@ // #pragma once +#include + namespace _IOglTF_NS_ { void *_gltfFormatInfo (FbxWriter::EInfoRequest pRequest, int pId) ; @@ -62,23 +64,23 @@ class IOglTF : public FbxPlugin { static const unsigned int FRAGMENT_SHADER =35632 ; static const unsigned int VERTEX_SHADER =35633 ; // accessor::type (https://github.com/KhronosGroup/glTF/blob/master/specification/accessor.schema.json) - static const utility::char_t *szSCALAR ; - static const utility::char_t *szFLOAT ; - static const utility::char_t *szVEC2 ; - static const utility::char_t *szVEC3 ; - static const utility::char_t *szVEC4 ; - static const utility::char_t *szINT ; - static const utility::char_t *szIVEC2 ; - static const utility::char_t *szIVEC3 ; - static const utility::char_t *szIVEC4 ; - static const utility::char_t *szBOOL ; - static const utility::char_t *szBVEC2 ; - static const utility::char_t *szBVEC3 ; - static const utility::char_t *szBVEC4 ; - static const utility::char_t *szMAT2 ; - static const utility::char_t *szMAT3 ; - static const utility::char_t *szMAT4 ; - static const utility::char_t *szSAMPLER_2D ; + static const char *szSCALAR ; + static const char *szFLOAT ; + static const char *szVEC2 ; + static const char *szVEC3 ; + static const char *szVEC4 ; + static const char *szINT ; + static const char *szIVEC2 ; + static const char *szIVEC3 ; + static const char *szIVEC4 ; + static const char *szBOOL ; + static const char *szBVEC2 ; + static const char *szBVEC3 ; + static const char *szBVEC4 ; + static const char *szMAT2 ; + static const char *szMAT3 ; + static const char *szMAT4 ; + static const char *szSAMPLER_2D ; // bufferView::Target (https://github.com/KhronosGroup/glTF/blob/master/specification/bufferView.schema.json) static const unsigned int ARRAY_BUFFER =34962 ; static const unsigned int ELEMENT_ARRAY_BUFFER =34963 ; @@ -118,9 +120,9 @@ class IOglTF : public FbxPlugin { static const unsigned int REPEAT =10497 ; // - static const web::json::value Identity2 ; - static const web::json::value Identity3 ; - static const web::json::value Identity4 ; + static const Json::Value Identity2 ; + static const Json::Value Identity3 ; + static const Json::Value Identity4 ; protected: explicit IOglTF (const FbxPluginDef &pDefinition, FbxModule pLibHandle) : FbxPlugin (pDefinition, pLibHandle) { @@ -134,14 +136,14 @@ class IOglTF : public FbxPlugin { template static unsigned int accessorComponentType () ; template - static const utility::char_t *accessorType (int size, int dim =1) ; - static unsigned int techniqueParameters (const utility::char_t *szType, int compType =FLOAT) ; - static const utility::char_t *glslAccessorType (unsigned int glType) ; - static const utility::string_t glslShaderType (unsigned int glType) ; - static const utility::char_t *mimeType (const utility::char_t *szFilename) ; + static const char *accessorType (int size, int dim =1) ; + static unsigned int techniqueParameters (const char *szType, int compType =FLOAT) ; + static const char *glslAccessorType (unsigned int glType) ; + static const std::string glslShaderType (unsigned int glType) ; + static const char *mimeType (const char *szFilename) ; // Online uri generator: http://bran.name/dump/data-uri-generator/ - static const utility::string_t dataURI (const utility::string_t fileName) ; - static const utility::string_t dataURI (memoryStream &stream) ; + static const std::string dataURI (const std::string fileName) ; + static const std::string dataURI (memoryStream &stream) ; } ; @@ -168,23 +170,23 @@ template if ( tp == iFloat ) return (FLOAT) ; if ( tp == iBool ) return (BOOL) ; - ucout << U("IOglTF::accessorComponentType() / hash code: ") << std::hex << typeid (T).hash_code () << std::endl ; - ucout << U("char: ") << std::hex << typeid (char).hash_code () << std::endl ; - ucout << U("int8_t: ") << std::hex << typeid (int8_t).hash_code () << std::endl ; - ucout << U("unsigned char: ") << std::hex << typeid (unsigned char).hash_code () << std::endl ; - ucout << U("uint8_t: ") << std::hex << typeid (uint8_t).hash_code () << std::endl ; - ucout << U("short: ") << std::hex << typeid (short).hash_code () << std::endl ; - ucout << U("unsigned short: ") << std::hex << typeid (unsigned short).hash_code () << std::endl ; - ucout << U("int: ") << std::hex << typeid (int).hash_code () << std::endl ; - ucout << U("unsigned int: ") << std::hex << typeid (unsigned int).hash_code () << std::endl ; - ucout << U("float: ") << std::hex << typeid (float).hash_code () << std::endl ; - ucout << U("bool: ") << std::hex << typeid (bool).hash_code () << std::endl ; + std::cout << ("IOglTF::accessorComponentType() / hash code: ") << std::hex << typeid (T).hash_code () << std::endl ; + std::cout << ("char: ") << std::hex << typeid (char).hash_code () << std::endl ; + std::cout << ("int8_t: ") << std::hex << typeid (int8_t).hash_code () << std::endl ; + std::cout << ("unsigned char: ") << std::hex << typeid (unsigned char).hash_code () << std::endl ; + std::cout << ("uint8_t: ") << std::hex << typeid (uint8_t).hash_code () << std::endl ; + std::cout << ("short: ") << std::hex << typeid (short).hash_code () << std::endl ; + std::cout << ("unsigned short: ") << std::hex << typeid (unsigned short).hash_code () << std::endl ; + std::cout << ("int: ") << std::hex << typeid (int).hash_code () << std::endl ; + std::cout << ("unsigned int: ") << std::hex << typeid (unsigned int).hash_code () << std::endl ; + std::cout << ("float: ") << std::hex << typeid (float).hash_code () << std::endl ; + std::cout << ("bool: ") << std::hex << typeid (bool).hash_code () << std::endl ; _ASSERTE( false ) ; return (0) ; } template -/*static*/ const utility::char_t *IOglTF::accessorType (int size, int dim) { +/*static*/ const char *IOglTF::accessorType (int size, int dim) { if ( dim == 1 ) { int type =IOglTF::accessorComponentType () ; switch ( size ) { @@ -201,7 +203,7 @@ template } } _ASSERTE( false ) ; - return (U("")) ; + return (("")) ; } } diff --git a/IO-glTF/JsonPrettify.cpp b/IO-glTF/JsonPrettify.cpp index 0830d2b..555db88 100644 --- a/IO-glTF/JsonPrettify.cpp +++ b/IO-glTF/JsonPrettify.cpp @@ -24,152 +24,152 @@ namespace _IOglTF_NS_ { -/*static*/ web::json::value JsonPrettify::sNull =web::json::value::null () ; - -void JsonPrettify::serialize (utility::ostream_t &stream) { - serialize (_json, stream) ; -} - -void JsonPrettify::serialize (web::json::value &val, utility::ostream_t &stream) { - formatValue (val, stream) ; -} - -void JsonPrettify::indent (utility::ostream_t &stream) { - stream << utility::string_t (_level, '\t') ; -} - -void JsonPrettify::format_string (const utility::string_t &st, utility::ostream_t &stream) { - stream << U('"') ; - utility::string_t escaped ; - JsonPrettify::append_escape_string (escaped, st) ; - stream << escaped ; - stream << U('"') ; -} - -void JsonPrettify::format_boolean (const bool val, utility::ostream_t &stream) { - stream << val ? U("true") : U("false") ; -} - -void JsonPrettify::format_integer (const int val, utility::ostream_t &stream) { - stream << val ; -} - -void JsonPrettify::format_double (const double val, utility::ostream_t &stream) { - stream << val ; -} - -void JsonPrettify::format_null (utility::ostream_t &stream) { - stream << U("null") ; -} - -void JsonPrettify::formatValue (web::json::value &val, utility::ostream_t &stream) { - if ( val.is_array () ) - formatArray (val.as_array (), stream) ; - else if ( val.is_object () ) - formatObject (val.as_object (), stream) ; - else if ( val.is_string () ) - format_string (val.as_string (), stream) ; - else if ( val.is_boolean () ) - format_boolean (val.as_bool (), stream) ; - else if ( val.is_integer () ) - format_integer (val.as_integer (), stream) ; - else if ( val.is_double () ) - format_double (val.as_double (), stream) ; - else if ( val.is_null () ) - format_null (stream) ; -} - -void JsonPrettify::formatPair (utility::string_t &key, web::json::value &val, utility::ostream_t &stream) { - indent (stream) ; - format_string (key, stream) ; - stream << U(": ") ; - formatValue (val, stream) ; -} - -void JsonPrettify::formatArray (web::json::array &arr, utility::ostream_t &stream) { - stream << U("[\n") ; - if ( arr.size () ) { - _level++ ; - auto lastElement =arr.end () - 1 ; - for ( auto iter =arr.begin () ; iter != lastElement ; ++iter ) { - indent (stream) ; - formatValue (*iter, stream) ; - stream << U(",\n") ; - } - indent (stream) ; - formatValue (*lastElement, stream) ; - stream << U("\n") ; - _level-- ; - } - indent (stream) ; - stream << U("]") ; -} - -void JsonPrettify::formatObject (web::json::object &obj, utility::ostream_t &stream) { - stream << U("{\n") ; - if ( !obj.empty () ) { - _level++ ; - auto lastElement =obj.end () - 1 ; - for ( auto iter =obj.begin () ; iter != lastElement ; ++iter ) { - formatPair (iter->first, iter->second, stream) ; - stream << U(",\n") ; - } - formatPair (lastElement->first, lastElement->second, stream) ; - stream << U("\n") ; - _level-- ; - } - indent (stream) ; - stream << U("}") ; -} - -// Copied from Casablanca REST SDK - json_serialization.cpp #75 -template -void JsonPrettify::append_escape_string (std::basic_string &str, const std::basic_string &escaped) { - for ( const auto &ch : escaped ) { - switch ( ch ) { - case '\"': - str +='\\' ; - str +='\"' ; - break ; - case '\\': - str +='\\' ; - str +='\\' ; - break ; - case '\b': - str +='\\' ; - str +='b' ; - break ; - case '\f': - str +='\\' ; - str +='f' ; - break ; - case '\r': - str +='\\' ; - str +='r' ; - break ; - case '\n': - str +='\\' ; - str +='n' ; - break ; - case '\t': - str +='\\' ; - str +='t' ; - break ; - default: - // If a control character then must unicode escaped. - if ( ch >= 0 && ch <= 0x1F ) { - static const std::array intToHex ={ { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' } } ; - str +='\\' ; - str +='u' ; - str +='0' ; - str +='0' ; - str +=intToHex [(ch & 0xF0) >> 4] ; - str +=intToHex [ch & 0x0F] ; - } else { - str +=ch ; - } - } - } -} +///*static*/ Json::Value JsonPrettify::sNull ; +// +//void JsonPrettify::serialize (utility::ostream_t &stream) { +// serialize (_json, stream) ; +//} +// +//void JsonPrettify::serialize (Json::Value &val, utility::ostream_t &stream) { +// formatValue (val, stream) ; +//} +// +//void JsonPrettify::indent (utility::ostream_t &stream) { +// stream << std::string (_level, '\t') ; +//} +// +//void JsonPrettify::format_string (const std::string &st, utility::ostream_t &stream) { +// stream << ('"') ; +// std::string escaped ; +// JsonPrettify::append_escape_string (escaped, st) ; +// stream << escaped ; +// stream << ('"') ; +//} +// +//void JsonPrettify::format_boolean (const bool val, utility::ostream_t &stream) { +// stream << val ? ("true") : ("false") ; +//} +// +//void JsonPrettify::format_integer (const int val, utility::ostream_t &stream) { +// stream << val ; +//} +// +//void JsonPrettify::format_double (const double val, utility::ostream_t &stream) { +// stream << val ; +//} +// +//void JsonPrettify::format_null (utility::ostream_t &stream) { +// stream << ("null") ; +//} +// +//void JsonPrettify::formatValue (Json::Value &val, utility::ostream_t &stream) { +// if ( val.is_array () ) +// formatArray (val.as_array (), stream) ; +// else if ( val.is_object () ) +// formatObject (val.as_object (), stream) ; +// else if ( val.is_string () ) +// format_string (val.asString (), stream) ; +// else if ( val.is_boolean () ) +// format_boolean (val.as_bool (), stream) ; +// else if ( val.is_integer () ) +// format_integer (val.asInt (), stream) ; +// else if ( val.is_double () ) +// format_double (val.as_double (), stream) ; +// else if ( val.isNull () ) +// format_null (stream) ; +//} +// +//void JsonPrettify::formatPair (std::string &key, Json::Value &val, utility::ostream_t &stream) { +// indent (stream) ; +// format_string (key, stream) ; +// stream << (": ") ; +// formatValue (val, stream) ; +//} +// +//void JsonPrettify::formatArray (web::json::array &arr, utility::ostream_t &stream) { +// stream << ("[\n") ; +// if ( arr.size () ) { +// _level++ ; +// auto lastElement =arr.end () - 1 ; +// for ( auto iter =arr.begin () ; iter != lastElement ; ++iter ) { +// indent (stream) ; +// formatValue (*iter, stream) ; +// stream << (",\n") ; +// } +// indent (stream) ; +// formatValue (*lastElement, stream) ; +// stream << ("\n") ; +// _level-- ; +// } +// indent (stream) ; +// stream << ("]") ; +//} +// +//void JsonPrettify::formatObject (web::json::object &obj, utility::ostream_t &stream) { +// stream << ("{\n") ; +// if ( !obj.empty () ) { +// _level++ ; +// auto lastElement =obj.end () - 1 ; +// for ( auto iter =obj.begin () ; iter != lastElement ; ++iter ) { +// formatPair (iter->first, iter->second, stream) ; +// stream << (",\n") ; +// } +// formatPair (lastElement->first, lastElement->second, stream) ; +// stream << ("\n") ; +// _level-- ; +// } +// indent (stream) ; +// stream << ("}") ; +//} +// +//// Copied from Casablanca REST SDK - json_serialization.cpp #75 +//template +//void JsonPrettify::append_escape_string (std::basic_string &str, const std::basic_string &escaped) { +// for ( const auto &ch : escaped ) { +// switch ( ch ) { +// case '\"': +// str +='\\' ; +// str +='\"' ; +// break ; +// case '\\': +// str +='\\' ; +// str +='\\' ; +// break ; +// case '\b': +// str +='\\' ; +// str +='b' ; +// break ; +// case '\f': +// str +='\\' ; +// str +='f' ; +// break ; +// case '\r': +// str +='\\' ; +// str +='r' ; +// break ; +// case '\n': +// str +='\\' ; +// str +='n' ; +// break ; +// case '\t': +// str +='\\' ; +// str +='t' ; +// break ; +// default: +// // If a control character then must unicode escaped. +// if ( ch >= 0 && ch <= 0x1F ) { +// static const std::array intToHex ={ { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' } } ; +// str +='\\' ; +// str +='u' ; +// str +='0' ; +// str +='0' ; +// str +=intToHex [(ch & 0xF0) >> 4] ; +// str +=intToHex [ch & 0x0F] ; +// } else { +// str +=ch ; +// } +// } +// } +//} } diff --git a/IO-glTF/JsonPrettify.h b/IO-glTF/JsonPrettify.h index b4dd823..db2a834 100644 --- a/IO-glTF/JsonPrettify.h +++ b/IO-glTF/JsonPrettify.h @@ -22,34 +22,34 @@ namespace _IOglTF_NS_ { -class JsonPrettify { - static web::json::value sNull ; - web::json::value &_json ; - int _level ; - -protected: - JsonPrettify () : _json (JsonPrettify::sNull) {} - - void serialize (web::json::value &val, utility::ostream_t &stream) ; - void indent (utility::ostream_t &stream) ; - void format_string (const utility::string_t &st, utility::ostream_t &stream) ; - void format_boolean (const bool val, utility::ostream_t &stream) ; - void format_integer (const int val, utility::ostream_t &stream) ; - void format_double (const double val, utility::ostream_t &stream) ; - void format_null (utility::ostream_t &stream) ; - void formatValue (web::json::value &val, utility::ostream_t &stream) ; - void formatPair (utility::string_t &key, web::json::value &val, utility::ostream_t &stream) ; - void formatArray (web::json::array &arr, utility::ostream_t &stream) ; - void formatObject (web::json::object &obj, utility::ostream_t &stream) ; - - template - static void append_escape_string (std::basic_string &str, const std::basic_string &escaped) ; - -public: - JsonPrettify (web::json::value &json) : _json (json), _level (0) {} - - void serialize (utility::ostream_t &stream) ; - -} ; +//class JsonPrettify { +// static Json::Value sNull ; +// Json::Value &_json ; +// int _level ; +// +//protected: +// JsonPrettify () : _json (JsonPrettify::sNull) {} +// +// void serialize (Json::Value &val, utility::ostream_t &stream) ; +// void indent (utility::ostream_t &stream) ; +// void format_string (const std::string &st, utility::ostream_t &stream) ; +// void format_boolean (const bool val, utility::ostream_t &stream) ; +// void format_integer (const int val, utility::ostream_t &stream) ; +// void format_double (const double val, utility::ostream_t &stream) ; +// void format_null (utility::ostream_t &stream) ; +// void formatValue (Json::Value &val, utility::ostream_t &stream) ; +// void formatPair (std::string &key, Json::Value &val, utility::ostream_t &stream) ; +// void formatArray (web::json::array &arr, utility::ostream_t &stream) ; +// void formatObject (web::json::object &obj, utility::ostream_t &stream) ; +// +// template +// static void append_escape_string (std::basic_string &str, const std::basic_string &escaped) ; +// +//public: +// JsonPrettify (Json::Value &json) : _json (json), _level (0) {} +// +// void serialize (utility::ostream_t &stream) ; +// +//} ; } diff --git a/IO-glTF/StdAfx.h b/IO-glTF/StdAfx.h index 140debc..f11a208 100644 --- a/IO-glTF/StdAfx.h +++ b/IO-glTF/StdAfx.h @@ -49,19 +49,14 @@ #include #include -// C++ REST SDK (codename "Casablanca") -// https://casablanca.codeplex.com/ -#include -#include // JSON library -#include // URI library -typedef web::json::value JsonValue ; -typedef web::json::value::value_type JsonValueType ; +#include "jsoncpp/json-forwards.h" +typedef Json::Value JsonValue ; #include -typedef std::basic_regex uregex ; -//typedef std::match_results umatch ; -typedef std::match_results umatch ; -//typedef std::match_results umatch ; +typedef std::basic_regex uregex ; +//typedef std::match_results umatch ; +typedef std::match_results umatch ; +//typedef std::match_results umatch ; // C++ FBX SDK // http://www.autodeks.com/developfbx diff --git a/IO-glTF/glslShader.cpp b/IO-glTF/glslShader.cpp index aceab75..e4de327 100644 --- a/IO-glTF/glslShader.cpp +++ b/IO-glTF/glslShader.cpp @@ -23,60 +23,60 @@ namespace _IOglTF_NS_ { -//utility::string_t vs [8] ={ -// U("position"), U("normal"), U("joint"), U("jointMat"), U("weight"), -// U("normalMatrix"), U("modelViewMatrix"), U("projectionMatrix") +//std::string vs [8] ={ +// ("position"), ("normal"), ("joint"), ("jointMat"), ("weight"), +// ("normalMatrix"), ("modelViewMatrix"), ("projectionMatrix") //} ; // -//utility::string_t fs [8] ={ -// U("position"), U("normal"), U("joint"), U("jointMat"), U("weight"), -// U("normalMatrix"), U("modelViewMatrix"), U("projectionMatrix") +//std::string fs [8] ={ +// ("position"), ("normal"), ("joint"), ("jointMat"), ("weight"), +// ("normalMatrix"), ("modelViewMatrix"), ("projectionMatrix") //} ; -glslShader::glslShader (const utility::char_t *glslVersion /*=nullptr*/) { - _declarations =U("") ; +glslShader::glslShader (const char *glslVersion /*=nullptr*/) { + _declarations =("") ; if ( glslVersion ) - _declarations +=U("#version ") + utility::string_t (glslVersion) + U("\n") ; - _declarations +=U("precision highp float ;\n") ; - _body =U("") ; + _declarations +=("#version ") + std::string (glslVersion) + ("\n") ; + _declarations +=("precision highp float ;\n") ; + _body =("") ; } glslShader::~glslShader () { } -utility::string_t &glslShader::name () { +std::string &glslShader::name () { return (_name) ; } -void glslShader::_addDeclaration (utility::string_t qualifier, utility::string_t symbol, unsigned int type, size_t count /*=1*/, bool forcesAsAnArray /*=false*/) { +void glslShader::_addDeclaration (std::string qualifier, std::string symbol, unsigned int type, size_t count /*=1*/, bool forcesAsAnArray /*=false*/) { if ( this->hasSymbol (symbol) == false ) { - utility::string_t szType =IOglTF::glslShaderType (type) ; - utility::string_t declaration =qualifier + U(" ") + szType + U(" ") + symbol ; + std::string szType =IOglTF::glslShaderType (type) ; + std::string declaration =qualifier + (" ") + szType + (" ") + symbol ; if ( count > 1 || forcesAsAnArray == true ) - declaration +=U("[") + utility::conversions::to_string_t ((int)count) + U("]") ; - declaration +=U(" ;\n") ; + declaration +=("[") + utility::conversions::to_string_t ((int)count) + ("]") ; + declaration +=(" ;\n") ; _declarations += declaration ; _allSymbols [symbol] =symbol ; } } -void glslShader::addAttribute (utility::string_t symbol, unsigned int type, size_t count /*=1*/, bool forcesAsAnArray /*=false*/) { - symbol =U("a_") + symbol ; - _addDeclaration (U("attribute"), symbol, type, count, forcesAsAnArray) ; +void glslShader::addAttribute (std::string symbol, unsigned int type, size_t count /*=1*/, bool forcesAsAnArray /*=false*/) { + symbol =("a_") + symbol ; + _addDeclaration (("attribute"), symbol, type, count, forcesAsAnArray) ; } -void glslShader::addUniform (utility::string_t symbol, unsigned int type, size_t count /*=1*/, bool forcesAsAnArray /*=false*/) { - symbol =U("u_") + symbol ; - _addDeclaration (U("uniform"), symbol, type, count, forcesAsAnArray) ; +void glslShader::addUniform (std::string symbol, unsigned int type, size_t count /*=1*/, bool forcesAsAnArray /*=false*/) { + symbol =("u_") + symbol ; + _addDeclaration (("uniform"), symbol, type, count, forcesAsAnArray) ; } -void glslShader::addVarying (utility::string_t symbol, unsigned int type, size_t count /*=1*/, bool forcesAsAnArray /*=false*/) { - symbol =U("v_") + symbol ; - _addDeclaration (U("varying"), symbol, type, count, forcesAsAnArray) ; +void glslShader::addVarying (std::string symbol, unsigned int type, size_t count /*=1*/, bool forcesAsAnArray /*=false*/) { + symbol =("v_") + symbol ; + _addDeclaration (("varying"), symbol, type, count, forcesAsAnArray) ; } -bool glslShader::hasSymbol (const utility::string_t &symbol) { +bool glslShader::hasSymbol (const std::string &symbol) { return (_allSymbols.count (symbol) > 0) ; } @@ -88,38 +88,25 @@ void glslShader::appendCode (const char *format, ...) { vsprintf_s (buffer, format, args) ; #else vsprintf (buffer, format, args) ; -#endif - _body +=utility::conversions::to_string_t (buffer) ; - va_end (args) ; -} - -void glslShader::appendCode (const utility::char_t *format, ...) { - utility::char_t buffer [1000] ; - va_list args ; - va_start (args, format) ; -#if defined(_WIN32) || defined(_WIN64) - _vstprintf_s (buffer, format, args) ; -#else - vsprintf (buffer, format, args) ; #endif _body +=buffer ; va_end (args) ; } -//void glslShader::appendCode (const utility::char_t *code) { +//void glslShader::appendCode (const char *code) { // _body +=code ; //} -utility::string_t glslShader::source () { +std::string glslShader::source () { return (_declarations + body ()) ; } -utility::string_t glslShader::body () { - return (U("void main (void) {\n") + _body + U("}\n")) ; +std::string glslShader::body () { + return (("void main (void) {\n") + _body + ("}\n")) ; } //----------------------------------------------------------------------------- -glslTech::glslTech (web::json::value technique, web::json::value values, web::json::value gltf, const utility::char_t *glslVersion) +glslTech::glslTech (Json::Value technique, Json::Value values, Json::Value gltf, const char *glslVersion) : _vertexShader (glslVersion), _fragmentShader (glslVersion), _bHasNormals (false), _bHasJoint (false), _bHasWeight (false), _bHasSkin (false), _bHasTexTangent (false), _bHasTexBinormal (false), _bModelContainsLights (false), _bLightingIsEnabled (false), _bHasAmbientLight (false), _bHasSpecularLight (false), _bHasNormalMap (false) @@ -135,8 +122,8 @@ glslTech::glslTech (web::json::value technique, web::json::value values, web::js glslTech::~glslTech () { } -/*static*/ utility::string_t glslTech::format (const utility::char_t *format, ...) { - utility::char_t buffer [1000] ; +/*static*/ std::string glslTech::format (const char *format, ...) { + char buffer [1000] ; va_list args ; va_start (args, format) ; #if defined(_WIN32) || defined(_WIN64) @@ -148,53 +135,53 @@ glslTech::~glslTech () { return (buffer) ; } -const utility::string_t glslTech::needsVarying (const utility::char_t *semantic) { - static utility::string_t varyings [] ={ - U("^position$"), U("^normal$"), - U("^texcoord([0-9]+)$") - //U("^light([0-9]+)Transform$") +const std::string glslTech::needsVarying (const char *semantic) { + static std::string varyings [] ={ + ("^position$"), ("^normal$"), + ("^texcoord([0-9]+)$") + //("^light([0-9]+)Transform$") } ; - //static utility::string_t varyingsMapping [] ={ - // U("texcoord([0-9]+)"), U("texcoord%s"), - // U("light([0-9]+)Transform"), U("light%sDirection") + //static std::string varyingsMapping [] ={ + // ("texcoord([0-9]+)"), ("texcoord%s"), + // ("light([0-9]+)Transform"), ("light%sDirection") //} ; - int nb =sizeof (varyings) / sizeof (utility::string_t) ; - //int nb2 =sizeof (varyingsMapping) / sizeof (utility::string_t) / 2 ; + int nb =sizeof (varyings) / sizeof (std::string) ; + //int nb2 =sizeof (varyingsMapping) / sizeof (std::string) / 2 ; for ( int i =0 ; i < nb ; i++ ) { uregex regex (varyings [i], std::regex_constants::ECMAScript | std::regex_constants::icase) ; if ( std::regex_search (semantic, regex) ) { /*for ( int j =0 ; j < nb2 ; j++ ) { if ( varyings [i] == varyingsMapping [j * 2] ) { uregex regex2 (varyings [i]) ; - utility::string_t st (semantic) ; + std::string st (semantic) ; //umatch matches ; //if ( std::regex_match (st.cbegin (), st.cend (), matches, regex2) ) - // ucout << L"The matching text is:" << matches.str () << std::endl ; + // std::cout << L"The matching text is:" << matches.str () << std::endl ; umatch mr ; //bool results =std::regex_search (st.cbegin (), st.cend (), regex2, std::regex_constants::match_default) ; bool results =std::regex_search (st, mr, regex2) ; //for ( size_t k =0 ; k < mr.size () ; ++k ) - // ucout << k << U(" ") << mr [k].str () << std::endl ; - utility::string_t st2 =format (varyingsMapping [j * 2 + 1].c_str (), mr [1].str ().c_str ()) ; + // std::cout << k << (" ") << mr [k].str () << std::endl ; + std::string st2 =format (varyingsMapping [j * 2 + 1].c_str (), mr [1].str ().c_str ()) ; return (st2) ; } }*/ return (varyings [i]) ; } } - return (U("")) ; + return (("")) ; } -/*static*/ bool glslTech::isVertexShaderSemantic (const utility::char_t *semantic) { - static utility::string_t vs_semantics [] ={ - U("^position$"), U("^normal$"), U("^normalMatrix$"), U("^modelViewMatrix$"), U("^projectionMatrix$"), - U("^texcoord([0-9]+)$"), U("^light([0-9]+)Transform$") +/*static*/ bool glslTech::isVertexShaderSemantic (const char *semantic) { + static std::string vs_semantics [] ={ + ("^position$"), ("^normal$"), ("^normalMatrix$"), ("^modelViewMatrix$"), ("^projectionMatrix$"), + ("^texcoord([0-9]+)$"), ("^light([0-9]+)Transform$") } ; - int nb =sizeof (vs_semantics) / sizeof (utility::string_t) ; + int nb =sizeof (vs_semantics) / sizeof (std::string) ; for ( int i =0 ; i < nb ; i++ ) { uregex regex (vs_semantics [i], std::regex_constants::ECMAScript | std::regex_constants::icase) ; if ( std::regex_search (semantic, regex) ) @@ -203,13 +190,13 @@ const utility::string_t glslTech::needsVarying (const utility::char_t *semantic) return (false) ; } -/*static*/ bool glslTech::isFragmentShaderSemantic (const utility::char_t *semantic) { - static utility::string_t fs_semantics [] ={ - U("^ambient$"), U("^diffuse$"), U("^emission$"), U("^specular$"), U("^shininess$"), - U("^reflective$"), U("^reflectivity$"), U("^transparent$"), U("^transparency$"), - U("^light([0-9]+)Color$") +/*static*/ bool glslTech::isFragmentShaderSemantic (const char *semantic) { + static std::string fs_semantics [] ={ + ("^ambient$"), ("^diffuse$"), ("^emission$"), ("^specular$"), ("^shininess$"), + ("^reflective$"), ("^reflectivity$"), ("^transparent$"), ("^transparency$"), + ("^light([0-9]+)Color$") } ; - int nb =sizeof (fs_semantics) / sizeof (utility::string_t) ; + int nb =sizeof (fs_semantics) / sizeof (std::string) ; for ( int i =0 ; i < nb ; i++ ) { uregex regex (fs_semantics [i], std::regex_constants::ECMAScript | std::regex_constants::icase) ; if ( std::regex_search (semantic, regex) ) @@ -218,38 +205,39 @@ const utility::string_t glslTech::needsVarying (const utility::char_t *semantic) return (false) ; } -void glslTech::prepareParameters (web::json::value technique) { +void glslTech::prepareParameters (Json::Value technique) { // Parameters / attribute - uniforms - varying - web::json::value parameters =technique [U("parameters")] ; - for ( auto iter =parameters.as_object ().begin () ; iter != parameters.as_object ().end () ; iter++ ) { - unsigned int iType =iter->second.as_object () [U("type")].as_integer () ; - bool bIsAttribute =technique [U("attributes")].has_field (U("a_") + iter->first) ; + auto ¶meters =technique [("parameters")] ; + auto memberNames = parameters.getMemberNames(); + for ( auto &name : memberNames ) { + unsigned int iType =parameters[name] [("type")].asInt () ; + bool bIsAttribute =technique [("attributes")].isMember (("a_") + name) ; - if ( glslTech::isVertexShaderSemantic (iter->first.c_str ()) ) { + if ( glslTech::isVertexShaderSemantic (name.c_str()) ) { if ( bIsAttribute ) - _vertexShader.addAttribute (iter->first, iType) ; + _vertexShader.addAttribute (name, iType) ; else - _vertexShader.addUniform (iter->first, iType) ; - utility::string_t v =needsVarying (iter->first.c_str ()) ; - if ( v != U("") ) { - _vertexShader.addVarying (iter->first, iType) ; - _fragmentShader.addVarying (iter->first, iType) ; + _vertexShader.addUniform (name, iType) ; + std::string v =needsVarying (name.c_str ()) ; + if ( ! v.empty() ) { + _vertexShader.addVarying (name, iType) ; + _fragmentShader.addVarying (name, iType) ; } } - if ( glslTech::isFragmentShaderSemantic (iter->first.c_str ()) ) { + if ( glslTech::isFragmentShaderSemantic (name.c_str()) ) { if ( bIsAttribute ) - _fragmentShader.addAttribute (iter->first, iType) ; + _fragmentShader.addAttribute (name, iType) ; else - _fragmentShader.addUniform (iter->first, iType) ; + _fragmentShader.addUniform (name, iType) ; } - if ( iter->second.has_field (U("semantic")) ) { - utility::string_t semantic =iter->second.as_object() [U("semantic")].as_string () ; - _bHasNormals |=semantic == U("NORMAL") ; - _bHasJoint |=semantic == U("JOINT") ; - _bHasWeight |=semantic == U("WEIGHT") ; - _bHasTexTangent |=semantic == U("TEXTANGENT") ; - _bHasTexBinormal |=semantic == U("TEXBINORMAL") ; + if ( parameters[name].isMember (("semantic")) ) { + std::string semantic =parameters[name] [("semantic")].asString () ; + _bHasNormals |=semantic == ("NORMAL") ; + _bHasJoint |=semantic == ("JOINT") ; + _bHasWeight |=semantic == ("WEIGHT") ; + _bHasTexTangent |=semantic == ("TEXTANGENT") ; + _bHasTexBinormal |=semantic == ("TEXBINORMAL") ; } } _bHasSkin =_bHasJoint && _bHasWeight ; @@ -258,29 +246,30 @@ void glslTech::prepareParameters (web::json::value technique) { void glslTech::hwSkinning () { // Handle hardware skinning, for now with a fixed limit of 4 influences if ( _bHasSkin ) { - _vertexShader.appendCode (U("mat4 skinMat =a_weight.x * u_jointMat [int(a_joint.x)] ;\n")) ; - _vertexShader.appendCode (U("skinMat +=a_weight.y * u_jointMat [int(a_joint.y)] ;\n")) ; - _vertexShader.appendCode (U("skinMat +=a_weight.z * u_jointMat [int(a_joint.z)] ;\n")) ; - _vertexShader.appendCode (U("skinMat +=a_weight.w * u_jointMat [int(a_joint.w)] ;\n")) ; - _vertexShader.appendCode (U("vec4 pos =u_modelViewMatrix * skinMat * vec4(a_position, 1.0) ;\n")) ; + _vertexShader.appendCode (("mat4 skinMat =a_weight.x * u_jointMat [int(a_joint.x)] ;\n")) ; + _vertexShader.appendCode (("skinMat +=a_weight.y * u_jointMat [int(a_joint.y)] ;\n")) ; + _vertexShader.appendCode (("skinMat +=a_weight.z * u_jointMat [int(a_joint.z)] ;\n")) ; + _vertexShader.appendCode (("skinMat +=a_weight.w * u_jointMat [int(a_joint.w)] ;\n")) ; + _vertexShader.appendCode (("vec4 pos =u_modelViewMatrix * skinMat * vec4(a_position, 1.0) ;\n")) ; if ( _bHasNormals ) - _vertexShader.appendCode (U("v_normal =u_normalMatrix * mat3(skinMat) * a_normal ;\n")) ; + _vertexShader.appendCode (("v_normal =u_normalMatrix * mat3(skinMat) * a_normal ;\n")) ; } else { - _vertexShader.appendCode (U("vec4 pos =u_modelViewMatrix * vec4(a_position, 1.0) ;\n")) ; + _vertexShader.appendCode (("vec4 pos =u_modelViewMatrix * vec4(a_position, 1.0) ;\n")) ; if ( _bHasNormals ) - _vertexShader.appendCode (U("v_normal =u_normalMatrix * a_normal ;\n")) ; + _vertexShader.appendCode (("v_normal =u_normalMatrix * a_normal ;\n")) ; } } -bool glslTech::lighting1 (web::json::value technique, web::json::value gltf) { +bool glslTech::lighting1 (Json::Value technique, Json::Value gltf) { // Lighting - web::json::value lights =gltf [U("lights")] ; - for ( auto iter =lights.as_object ().begin () ; iter != lights.as_object ().end () ; iter++ ) - _bModelContainsLights |=iter->second.as_object () [U("type")].as_string () != U("ambient") ; + auto &lights =gltf [("lights")] ; + auto memberNames = lights.getMemberNames(); + for ( auto &name : memberNames ) + _bModelContainsLights |=lights[name] [("type")].asString () != ("ambient") ; _bLightingIsEnabled =_bHasNormals && (_bModelContainsLights || true) ; // todo - default lighting option if ( _bLightingIsEnabled ) { - _fragmentShader.appendCode (U("vec3 normal =normalize (v_normal) ;\n")) ; - bool bDoubledSide =technique [U("extras")] [U("doubleSided")].as_bool () ; + _fragmentShader.appendCode (("vec3 normal =normalize (v_normal) ;\n")) ; + bool bDoubledSide =technique [("extras")] [("doubleSided")].asBool () ; if ( bDoubledSide ) _fragmentShader.appendCode ("if ( gl_FrontFacing == false ) normal =-normal ;\n") ; } else { @@ -292,45 +281,45 @@ bool glslTech::lighting1 (web::json::value technique, web::json::value gltf) { } // Color to cumulate all components and light contribution - _fragmentShader.appendCode (U("vec4 color =vec4(0., 0., 0., 0.) ;\n")) ; - _fragmentShader.appendCode (U("vec4 diffuse =vec4(0., 0., 0., 1.) ;\n")) ; + _fragmentShader.appendCode (("vec4 color =vec4(0., 0., 0., 0.) ;\n")) ; + _fragmentShader.appendCode (("vec4 diffuse =vec4(0., 0., 0., 1.) ;\n")) ; if ( _bModelContainsLights ) - _fragmentShader.appendCode (U("vec3 diffuseLight =vec3(0., 0., 0.) ;\n")) ; - web::json::value parameters =technique [U("parameters")] ; - if ( parameters.has_field (U("emission")) ) - _fragmentShader.appendCode (U("vec4 emission ;\n")) ; - if ( parameters.has_field (U("reflective")) ) - _fragmentShader.appendCode (U("vec4 reflective ;\n")) ; - if ( _bLightingIsEnabled && parameters.has_field (U("ambient")) ) - _fragmentShader.appendCode (U("vec4 ambient ;\n")) ; - if ( _bLightingIsEnabled && parameters.has_field (U("specular")) ) + _fragmentShader.appendCode (("vec3 diffuseLight =vec3(0., 0., 0.) ;\n")) ; + Json::Value parameters =technique [("parameters")] ; + if ( parameters.isMember (("emission")) ) + _fragmentShader.appendCode (("vec4 emission ;\n")) ; + if ( parameters.isMember (("reflective")) ) + _fragmentShader.appendCode (("vec4 reflective ;\n")) ; + if ( _bLightingIsEnabled && parameters.isMember (("ambient")) ) + _fragmentShader.appendCode (("vec4 ambient ;\n")) ; + if ( _bLightingIsEnabled && parameters.isMember (("specular")) ) _fragmentShader.appendCode ("vec4 specular ;\n") ; return (_bLightingIsEnabled) ; } -void glslTech::texcoords (web::json::value technique) { - web::json::value parameters =technique [U("parameters")] ; - utility::string_t texcoordAttributeSymbol =U("a_texcoord") ; - utility::string_t texcoordVaryingSymbol =U("v_texcoord") ; - std::map declaredTexcoordAttributes ; - std::map declaredTexcoordVaryings ; - utility::string_t slots []={ U("ambient"), U("diffuse"), U("emission"), U("reflective"), U("specular"), U("bump") } ; - const int slotsCount =sizeof (slots) / sizeof (utility::string_t) ; +void glslTech::texcoords (Json::Value technique) { + Json::Value parameters =technique [("parameters")] ; + std::string texcoordAttributeSymbol =("a_texcoord") ; + std::string texcoordVaryingSymbol =("v_texcoord") ; + std::map declaredTexcoordAttributes ; + std::map declaredTexcoordVaryings ; + std::string slots []={ ("ambient"), ("diffuse"), ("emission"), ("reflective"), ("specular"), ("bump") } ; + const int slotsCount =sizeof (slots) / sizeof (std::string) ; for ( size_t slotIndex =0 ; slotIndex < slotsCount ; slotIndex++ ) { - utility::string_t slot =slots [slotIndex] ; - if ( parameters.has_field (slot) == false ) + std::string slot =slots [slotIndex] ; + if ( parameters.isMember (slot) == false ) continue ; - unsigned int slotType =parameters [slot].as_object () [U("type")].as_integer () ; - if ( (!_bLightingIsEnabled) && ((slot == U("ambient")) || (slot == U("specular"))) ) { + unsigned int slotType =parameters [slot] [("type")].asInt () ; + if ( (!_bLightingIsEnabled) && ((slot == ("ambient")) || (slot == ("specular"))) ) { // As explained in https://github.com/KhronosGroup/glTF/issues/121 export all parameters when details is specified //todo addParameter (slot, slotType); continue ; } - if ( _bLightingIsEnabled && (slot == U("bump")) ) { + if ( _bLightingIsEnabled && (slot == ("bump")) ) { _bHasNormalMap =slotType == IOglTF::SAMPLER_2D && _bHasTexTangent && _bHasTexBinormal ; if ( _bHasNormalMap == true ) { - _vertexShader.addAttribute (U("textangent"), IOglTF::FLOAT_VEC3, 1, true) ; - _vertexShader.addAttribute (U("texbinormal"), IOglTF::FLOAT_VEC3, 1, true) ; + _vertexShader.addAttribute (("textangent"), IOglTF::FLOAT_VEC3, 1, true) ; + _vertexShader.addAttribute (("texbinormal"), IOglTF::FLOAT_VEC3, 1, true) ; _vertexShader.appendCode ("v_texbinormal =u_normalMatrix * a_texbinormal ;\n") ; _vertexShader.appendCode ("v_textangent =u_normalMatrix * a_textangent ;\n") ; _fragmentShader.appendCode ("vec4 bump ;\n") ; @@ -338,34 +327,34 @@ void glslTech::texcoords (web::json::value technique) { } if ( slotType == IOglTF::FLOAT_VEC4 ) { - utility::string_t slotColorSymbol =U("u_") + slot ; - _fragmentShader.appendCode (U("%s =%s ;\n"), slot.c_str (), slotColorSymbol.c_str ()) ; + std::string slotColorSymbol =("u_") + slot ; + _fragmentShader.appendCode (("%s =%s ;\n"), slot.c_str (), slotColorSymbol.c_str ()) ; //_fragmentShader.addUniformValue (slotType, 1, slot) ; } else if ( slotType == IOglTF::SAMPLER_2D ) { - utility::string_t semantic =technique [U("extras")] [U("texcoordBindings")] [slot].as_string () ; - utility::string_t texSymbol, texVSymbol ; - if ( slot == U("reflective") ) { + std::string semantic =technique [("extras")] [("texcoordBindings")] [slot].asString () ; + std::string texSymbol, texVSymbol ; + if ( slot == ("reflective") ) { texVSymbol =texcoordVaryingSymbol + utility::conversions::to_string_t ((int)declaredTexcoordVaryings.size ()) ; unsigned int reflectiveType =IOglTF::FLOAT_VEC2 ; // _vertexShader.addVarying (texVSymbol, reflectiveType) ; // _fragmentShader.addVarying (texVSymbol, reflectiveType) ; // Update Vertex shader for reflection - utility::string_t normalType =IOglTF::szVEC3 ; - _vertexShader.appendCode (U("%s normalizedVert =normalize (%s(pos)) ;\n"), normalType.c_str (), normalType.c_str ()) ; - _vertexShader.appendCode (U("%s r =reflect (normalizedVert, v_normal) ;\n"), normalType.c_str ()) ; - _vertexShader.appendCode (U("r.z +=1.0 ;\n")) ; - _vertexShader.appendCode (U("float m =2.0 * sqrt (dot (r, r)) ;\n")) ; - _vertexShader.appendCode (U("%s =(r.xy / m) + 0.5 ;\n"), texVSymbol.c_str ()) ; + std::string normalType =IOglTF::szVEC3 ; + _vertexShader.appendCode (("%s normalizedVert =normalize (%s(pos)) ;\n"), normalType.c_str (), normalType.c_str ()) ; + _vertexShader.appendCode (("%s r =reflect (normalizedVert, v_normal) ;\n"), normalType.c_str ()) ; + _vertexShader.appendCode (("r.z +=1.0 ;\n")) ; + _vertexShader.appendCode (("float m =2.0 * sqrt (dot (r, r)) ;\n")) ; + _vertexShader.appendCode (("%s =(r.xy / m) + 0.5 ;\n"), texVSymbol.c_str ()) ; declaredTexcoordVaryings [semantic] =texVSymbol ; } else { if ( declaredTexcoordAttributes.count (semantic) == 0 ) { texSymbol =texcoordAttributeSymbol + utility::conversions::to_string_t ((int)declaredTexcoordAttributes.size ()) ; texVSymbol =texcoordVaryingSymbol + utility::conversions::to_string_t ((int)declaredTexcoordVaryings.size ()) ; unsigned int texType =IOglTF::FLOAT_VEC2 ; - // _vertexShader.addAttribute (U("texcoord") + utility::conversions::to_string_t ((int)declaredTexcoordAttributes.size ()), texType) ; + // _vertexShader.addAttribute (("texcoord") + utility::conversions::to_string_t ((int)declaredTexcoordAttributes.size ()), texType) ; // _vertexShader.addVarying (texVSymbol, texType) ; // _fragmentShader.addVarying (texVSymbol, texType) ; - _vertexShader.appendCode (U("%s =%s ;\n"), texVSymbol.c_str (), texSymbol.c_str ()) ; + _vertexShader.appendCode (("%s =%s ;\n"), texVSymbol.c_str (), texSymbol.c_str ()) ; declaredTexcoordAttributes [semantic] =texSymbol ; declaredTexcoordVaryings [semantic] =texVSymbol ; @@ -375,13 +364,13 @@ void glslTech::texcoords (web::json::value technique) { } } - utility::string_t textureSymbol =U("u_") + slot ; - web::json::value textureParameter =parameters [slot] ; // get the texture - //_vertexShader.addUniform (texVSymbol, textureParameter [U("type")].as_integer ()) ; - //_fragmentShader.addUniform (texVSymbol, textureParameter [U("type")].as_integer ()) ; - if ( _bHasNormalMap == false && slot == U("bump") ) + std::string textureSymbol =("u_") + slot ; + Json::Value textureParameter =parameters [slot] ; // get the texture + //_vertexShader.addUniform (texVSymbol, textureParameter [("type")].asInt ()) ; + //_fragmentShader.addUniform (texVSymbol, textureParameter [("type")].asInt ()) ; + if ( _bHasNormalMap == false && slot == ("bump") ) continue ; - _fragmentShader.appendCode (U("%s =texture2D (%s, %s) ;\n"), slot.c_str (), textureSymbol.c_str (), texVSymbol.c_str ()) ; + _fragmentShader.appendCode (("%s =texture2D (%s, %s) ;\n"), slot.c_str (), textureSymbol.c_str (), texVSymbol.c_str ()) ; } } @@ -392,79 +381,83 @@ void glslTech::texcoords (web::json::value technique) { } } -web::json::value glslTech::lightNodes (web::json::value gltf) { - web::json::value ret =web::json::value::array () ; - for ( auto iter : gltf [U("nodes")].as_object () ) { - if ( iter.second.has_field (U("light")) ) - ret [ret.size ()] =web::json::value (iter.first) ; +Json::Value glslTech::lightNodes (Json::Value gltf) { + Json::Value ret( Json::arrayValue ) ; + auto &nodes = gltf["nodes"]; + auto memberNames = nodes.getMemberNames(); + for ( auto &name : memberNames ) { + if ( nodes[name].isMember (("light")) ) + ret [ret.size ()] =Json::Value (name) ; } return (ret) ; } -void glslTech::lighting2 (web::json::value technique, web::json::value gltf) { - web::json::value parameters =technique [U("parameters")] ; +void glslTech::lighting2 (Json::Value technique, Json::Value gltf) { + Json::Value parameters =technique [("parameters")] ; - utility::string_t lightingModel =technique [U("extras")] [U("lightingModel")].as_string () ; + std::string lightingModel =technique [("extras")] [("lightingModel")].asString () ; bool bHasSpecular = - parameters.has_field (U("specular")) && parameters.has_field (U("shininess")) - && (lightingModel == U("Phong") || lightingModel == U("Blinn")) ; + parameters.isMember (("specular")) && parameters.isMember (("shininess")) + && (lightingModel == ("Phong") || lightingModel == ("Blinn")) ; size_t lightIndex =0 ; - size_t nbLights =gltf [U("lights")].size () ; + size_t nbLights =gltf [("lights")].size () ; if ( _bLightingIsEnabled && nbLights ) { - web::json::value lightNodes =glslTech::lightNodes (gltf) ; - //if ( parameters.has_field (U("shininess")) && (!shininessObject) ) { + Json::Value lightNodes =glslTech::lightNodes (gltf) ; + //if ( parameters.isMember (("shininess")) && (!shininessObject) ) { - //std::vector ids ; - for ( auto iter : gltf [U("lights")].as_object () ) { + //std::vector ids ; + auto &lights = gltf [("lights")]; + auto memberNames = lights.getMemberNames(); + for ( auto name : memberNames ) { //ids.push_back (iter.first) ; - utility::string_t lightType =iter.second [U("type")].as_string () ; + std::string lightType =lights[name] [("type")].asString () ; // We ignore lighting if the only light we have is ambient - if ( (lightType == U("ambient")) && nbLights == 1 ) + if ( (lightType == ("ambient")) && nbLights == 1 ) continue ; for ( size_t j =0 ; j < lightNodes.size () ; j++, lightIndex++ ) { // Each light needs to be re-processed for each node - utility::string_t szLightIndex =glslTech::format (U("light%d"), (int)lightIndex) ; - utility::string_t szLightColor =glslTech::format (U("%sColor"), szLightIndex.c_str ()) ; - utility::string_t szLightTransform =glslTech::format (U("%sTransform"), szLightIndex.c_str ()) ; - utility::string_t szLightInverseTransform =glslTech::format (U("%sInverseTransform"), szLightIndex.c_str ()) ; - utility::string_t szLightConstantAttenuation =glslTech::format (U("%sConstantAttenuation"), szLightIndex.c_str ()) ; - utility::string_t szLightLinearAttenuation =glslTech::format (U("%sLinearAttenuation"), szLightIndex.c_str ()) ; - utility::string_t szLightQuadraticAttenuation =glslTech::format (U("%sQuadraticAttenuation"), szLightIndex.c_str ()) ; - utility::string_t szLightFallOffAngle =glslTech::format (U("%sFallOffAngle"), szLightIndex.c_str ()) ; - utility::string_t szLightFallOffExponent =glslTech::format (U("%sFallOffExponent"), szLightIndex.c_str ()) ; + std::string szLightIndex =glslTech::format (("light%d"), (int)lightIndex) ; + std::string szLightColor =glslTech::format (("%sColor"), szLightIndex.c_str ()) ; + std::string szLightTransform =glslTech::format (("%sTransform"), szLightIndex.c_str ()) ; + std::string szLightInverseTransform =glslTech::format (("%sInverseTransform"), szLightIndex.c_str ()) ; + std::string szLightConstantAttenuation =glslTech::format (("%sConstantAttenuation"), szLightIndex.c_str ()) ; + std::string szLightLinearAttenuation =glslTech::format (("%sLinearAttenuation"), szLightIndex.c_str ()) ; + std::string szLightQuadraticAttenuation =glslTech::format (("%sQuadraticAttenuation"), szLightIndex.c_str ()) ; + std::string szLightFallOffAngle =glslTech::format (("%sFallOffAngle"), szLightIndex.c_str ()) ; + std::string szLightFallOffExponent =glslTech::format (("%sFallOffExponent"), szLightIndex.c_str ()) ; if ( bHasSpecular ==true && _bHasSpecularLight == false ) { - _fragmentShader.appendCode (U("vec3 specularLight =vec3(0., 0., 0.) ;\n")) ; + _fragmentShader.appendCode (("vec3 specularLight =vec3(0., 0., 0.) ;\n")) ; _bHasSpecularLight =true ; } - if ( lightType == U("ambient") ) { + if ( lightType == ("ambient") ) { if ( _bHasAmbientLight == false ) { - _fragmentShader.appendCode (U("vec3 ambientLight =vec3(0., 0., 0.) ;\n")) ; + _fragmentShader.appendCode (("vec3 ambientLight =vec3(0., 0., 0.) ;\n")) ; _bHasAmbientLight =true ; } - _fragmentShader.appendCode (U("{\n")) ; + _fragmentShader.appendCode (("{\n")) ; //FIXME: what happens if multiple ambient light ? - _fragmentShader.appendCode (U("ambientLight +=u_%s ;\n"), szLightColor.c_str ()) ; - _fragmentShader.appendCode (U("}\n")) ; + _fragmentShader.appendCode (("ambientLight +=u_%s ;\n"), szLightColor.c_str ()) ; + _fragmentShader.appendCode (("}\n")) ; } else { - utility::string_t szVaryingLightDirection =glslTech::format (U("%sDirection"), szLightIndex.c_str ()) ; + std::string szVaryingLightDirection =glslTech::format (("%sDirection"), szLightIndex.c_str ()) ; _vertexShader.addVarying (szVaryingLightDirection, IOglTF::FLOAT_VEC3) ; _fragmentShader.addVarying (szVaryingLightDirection, IOglTF::FLOAT_VEC3) ; - if ( /*_vertexShader.hasSymbol (U("v_position")) == false - &&*/ (lightingModel == U("Phong") || lightingModel == U("Blinn") || lightType == U("spot")) + if ( /*_vertexShader.hasSymbol (("v_position")) == false + &&*/ (lightingModel == ("Phong") || lightingModel == ("Blinn") || lightType == ("spot")) ) { - //_vertexShader.addVarying (U("v_position"), IOglTF::FLOAT_VEC3) ; - //_fragmentShader.addVarying (U("v_position"), IOglTF::FLOAT_VEC3) ; - _vertexShader.appendCode (U("v_position =pos.xyz ;\n")) ; + //_vertexShader.addVarying (("v_position"), IOglTF::FLOAT_VEC3) ; + //_fragmentShader.addVarying (("v_position"), IOglTF::FLOAT_VEC3) ; + _vertexShader.appendCode (("v_position =pos.xyz ;\n")) ; } - _fragmentShader.appendCode (U("{\n")) ; - _fragmentShader.appendCode (U("float specularIntensity =0. ;\n")) ; - if ( lightType != U("directional") ) { + _fragmentShader.appendCode (("{\n")) ; + _fragmentShader.appendCode (("float specularIntensity =0. ;\n")) ; + if ( lightType != ("directional") ) { // shared_ptr lightConstantAttenuationParameter=addValue ("fs", "uniform", floatType, 1, lightConstantAttenuation, asset); // lightConstantAttenuationParameter->setValue ("value", description->getValue ("constantAttenuation")); // shared_ptr lightLinearAttenuationParameter=addValue ("fs", "uniform", floatType, 1, lightLinearAttenuation, asset); @@ -478,23 +471,23 @@ void glslTech::lighting2 (web::json::value technique, web::json::value gltf) { // lightTransformParameter->setValue (kNode, nodesIds [j]); // lightTransformParameter->setString (kSemantic, MODELVIEW); - if ( lightType == U("directional") ) - _vertexShader.appendCode (U("v_%s =mat3(u_%s) * vec3(0., 0., 1.) ;\n"), szVaryingLightDirection.c_str (), szLightTransform.c_str ()) ; + if ( lightType == ("directional") ) + _vertexShader.appendCode (("v_%s =mat3(u_%s) * vec3(0., 0., 1.) ;\n"), szVaryingLightDirection.c_str (), szLightTransform.c_str ()) ; else - _vertexShader.appendCode (U("v_%s =u_%s [3].xyz - pos.xyz ;\n"), szVaryingLightDirection.c_str (), szLightTransform.c_str ()) ; - _fragmentShader.appendCode (U("float attenuation =1.0 ;\n")) ; + _vertexShader.appendCode (("v_%s =u_%s [3].xyz - pos.xyz ;\n"), szVaryingLightDirection.c_str (), szLightTransform.c_str ()) ; + _fragmentShader.appendCode (("float attenuation =1.0 ;\n")) ; - if ( lightType != U("directional") ) { + if ( lightType != ("directional") ) { // Compute light attenuation from non-normalized light direction - _fragmentShader.appendCode (U("float range =length (%s) ;\n"), szVaryingLightDirection.c_str ()) ; - _fragmentShader.appendCode (U("attenuation =1.0 / (u_%s + (u_%s * range) + (u_%s * range * range)) ;\n"), + _fragmentShader.appendCode (("float range =length (%s) ;\n"), szVaryingLightDirection.c_str ()) ; + _fragmentShader.appendCode (("attenuation =1.0 / (u_%s + (u_%s * range) + (u_%s * range * range)) ;\n"), szLightConstantAttenuation.c_str (), szLightLinearAttenuation.c_str (), szLightQuadraticAttenuation.c_str () ) ; } // Compute lighting from normalized light direction - _fragmentShader.appendCode (U("vec3 l =normalize (v_%s) ;\n"), szVaryingLightDirection.c_str ()) ; + _fragmentShader.appendCode (("vec3 l =normalize (v_%s) ;\n"), szVaryingLightDirection.c_str ()) ; - if ( lightType == U("spot") ) { + if ( lightType == ("spot") ) { // shared_ptr lightInverseTransformParameter=addValue ("fs", "uniform", mat4Type, 1, lightInverseTransform, asset); // lightInverseTransformParameter->setValue (kNode, nodesIds [j]); // lightInverseTransformParameter->setString (kSemantic, MODELVIEWINVERSE); @@ -507,76 +500,76 @@ void glslTech::lighting2 (web::json::value technique, web::json::value gltf) { // As in OpenGL ES 2.0 programming guide // Raise spec issue about the angle // we can test this in the shader generation - _fragmentShader.appendCode (U("vec4 spotPosition =u_%s * vec4(v_position, 1.) ;\n"), szLightInverseTransform.c_str ()) ; - _fragmentShader.appendCode (U("float cosAngle =dot (vec3 (0., 0., -1.), normalize (spotPosition.xyz)) ;\n")) ; + _fragmentShader.appendCode (("vec4 spotPosition =u_%s * vec4(v_position, 1.) ;\n"), szLightInverseTransform.c_str ()) ; + _fragmentShader.appendCode (("float cosAngle =dot (vec3 (0., 0., -1.), normalize (spotPosition.xyz)) ;\n")) ; // doing this cos each pixel is just wrong (for performance) // need to find a way to specify that we pass the cos of a value - _fragmentShader.appendCode (U("if ( cosAngle > cos (radians (u_%s * 0.5)) ) {\n"), szLightFallOffAngle) ; - _fragmentShader.appendCode (U("attenuation *=max (0., pow (cosAngle, u_%s)) ;\n"), szLightFallOffExponent) ; + _fragmentShader.appendCode (("if ( cosAngle > cos (radians (u_%s * 0.5)) ) {\n"), szLightFallOffAngle.c_str()) ; + _fragmentShader.appendCode (("attenuation *=max (0., pow (cosAngle, u_%s)) ;\n"), szLightFallOffExponent.c_str()) ; } // We handle phong, blinn, constant and lambert if ( bHasSpecular ) { - _fragmentShader.appendCode (U("vec3 viewDir =-normalize (v_position) ;\n")) ; - if ( lightingModel == U("Phong") ) { + _fragmentShader.appendCode (("vec3 viewDir =-normalize (v_position) ;\n")) ; + if ( lightingModel == ("Phong") ) { if ( _bHasNormalMap ) { - _fragmentShader.appendCode (U("l *=bumpMatrix ;\n")) ; - _fragmentShader.appendCode (U("position *=bumpMatrix ;\n")) ; + _fragmentShader.appendCode (("l *=bumpMatrix ;\n")) ; + _fragmentShader.appendCode (("position *=bumpMatrix ;\n")) ; } - _fragmentShader.appendCode (U("float phongTerm =max (0.0, dot (reflect (-l, normal), viewDir)) ;\n")) ; - _fragmentShader.appendCode (U("specularIntensity =max (0., pow (phongTerm , u_shininess)) * attenuation ;\n")) ; - } else if ( lightingModel == U("Blinn") ) { - _fragmentShader.appendCode (U("vec3 h =normalize (l + viewDir) ;\n")) ; + _fragmentShader.appendCode (("float phongTerm =max (0.0, dot (reflect (-l, normal), viewDir)) ;\n")) ; + _fragmentShader.appendCode (("specularIntensity =max (0., pow (phongTerm , u_shininess)) * attenuation ;\n")) ; + } else if ( lightingModel == ("Blinn") ) { + _fragmentShader.appendCode (("vec3 h =normalize (l + viewDir) ;\n")) ; if ( _bHasNormalMap ) { - _fragmentShader.appendCode (U("h *=bumpMatrix ;\n")) ; - _fragmentShader.appendCode (U("l *=bumpMatrix ;\n")) ; + _fragmentShader.appendCode (("h *=bumpMatrix ;\n")) ; + _fragmentShader.appendCode (("l *=bumpMatrix ;\n")) ; } - _fragmentShader.appendCode (U("specularIntensity =max (0., pow (max (dot (normal, h), 0.), u_shininess)) * attenuation ;\n")) ; + _fragmentShader.appendCode (("specularIntensity =max (0., pow (max (dot (normal, h), 0.), u_shininess)) * attenuation ;\n")) ; } - _fragmentShader.appendCode (U("specularLight +=u_%s * specularIntensity ;\n"), szLightColor.c_str ()) ; + _fragmentShader.appendCode (("specularLight +=u_%s * specularIntensity ;\n"), szLightColor.c_str ()) ; } // Write diffuse - _fragmentShader.appendCode (U("diffuseLight +=u_%s * max (dot (normal, l), 0.) * attenuation ;\n"), szLightColor.c_str ()) ; - if ( lightType == U("spot") ) // Close previous scope beginning with "if (cosAngle > " ... - _fragmentShader.appendCode (U("}\n")) ; - _fragmentShader.appendCode (U("}\n")) ; + _fragmentShader.appendCode (("diffuseLight +=u_%s * max (dot (normal, l), 0.) * attenuation ;\n"), szLightColor.c_str ()) ; + if ( lightType == ("spot") ) // Close previous scope beginning with "if (cosAngle > " ... + _fragmentShader.appendCode (("}\n")) ; + _fragmentShader.appendCode (("}\n")) ; } } } } } -void glslTech::finalizingShaders (web::json::value technique, web::json::value gltf) { - web::json::value parameters =technique [U("parameters")] ; +void glslTech::finalizingShaders (Json::Value technique, Json::Value gltf) { + Json::Value parameters =technique [("parameters")] ; - if ( parameters.has_field (U("reflective")) ) - _fragmentShader.appendCode (U("diffuse.xyz +=reflective.xyz ;\n")) ; - if ( _bHasAmbientLight && _bLightingIsEnabled && parameters.has_field (U("ambient")) ) { - _fragmentShader.appendCode (U("ambient.xyz *=ambientLight ;\n")) ; - _fragmentShader.appendCode (U("color.xyz +=ambient.xyz;\n")) ; + if ( parameters.isMember (("reflective")) ) + _fragmentShader.appendCode (("diffuse.xyz +=reflective.xyz ;\n")) ; + if ( _bHasAmbientLight && _bLightingIsEnabled && parameters.isMember (("ambient")) ) { + _fragmentShader.appendCode (("ambient.xyz *=ambientLight ;\n")) ; + _fragmentShader.appendCode (("color.xyz +=ambient.xyz;\n")) ; } - if ( _bHasSpecularLight && _bLightingIsEnabled && parameters.has_field (U("specular")) ) { - _fragmentShader.appendCode (U("specular.xyz *=specularLight ;\n")) ; - _fragmentShader.appendCode (U("color.xyz +=specular.xyz ;\n")) ; + if ( _bHasSpecularLight && _bLightingIsEnabled && parameters.isMember (("specular")) ) { + _fragmentShader.appendCode (("specular.xyz *=specularLight ;\n")) ; + _fragmentShader.appendCode (("color.xyz +=specular.xyz ;\n")) ; } if ( _bModelContainsLights ) - _fragmentShader.appendCode (U("diffuse.xyz *=diffuseLight ;\n")) ; + _fragmentShader.appendCode (("diffuse.xyz *=diffuseLight ;\n")) ; else if ( _bHasNormals ) - _fragmentShader.appendCode (U("diffuse.xyz *=max (dot (normal, vec3(0., 0., 1.)), 0.) ;\n")) ; - _fragmentShader.appendCode (U("color.xyz +=diffuse.xyz ;\n")) ; + _fragmentShader.appendCode (("diffuse.xyz *=max (dot (normal, vec3(0., 0., 1.)), 0.) ;\n")) ; + _fragmentShader.appendCode (("color.xyz +=diffuse.xyz ;\n")) ; - if ( parameters.has_field (U("emission")) ) - _fragmentShader.appendCode (U("color.xyz +=emission.xyz ;\n")) ; + if ( parameters.isMember (("emission")) ) + _fragmentShader.appendCode (("color.xyz +=emission.xyz ;\n")) ; - bool hasTransparency =parameters.has_field (U("transparency")) ; + bool hasTransparency =parameters.isMember (("transparency")) ; if ( hasTransparency ) - _fragmentShader.appendCode (U("color =vec4(color.rgb * diffuse.a, diffuse.a * u_transparency) ;\n")) ; + _fragmentShader.appendCode (("color =vec4(color.rgb * diffuse.a, diffuse.a * u_transparency) ;\n")) ; else - _fragmentShader.appendCode (U("color =vec4(color.rgb * diffuse.a, diffuse.a) ;\n")) ; + _fragmentShader.appendCode (("color =vec4(color.rgb * diffuse.a, diffuse.a) ;\n")) ; - _fragmentShader.appendCode (U("gl_FragColor =color ;\n")) ; - _vertexShader.appendCode (U("gl_Position =u_projectionMatrix * pos ;\n")) ; + _fragmentShader.appendCode (("gl_FragColor =color ;\n")) ; + _vertexShader.appendCode (("gl_Position =u_projectionMatrix * pos ;\n")) ; } // NVidia hardware indices are reserved for built-in attributes: @@ -594,57 +587,57 @@ void glslTech::finalizingShaders (web::json::value technique, web::json::value g // gl_MultiTexCoord6 14 // gl_MultiTexCoord7 15 -//unsigned int semanticType (const utility::string_t &semantic) { -// static std::map semanticTypes ; -// if ( semantic.find (U("TEXCOORD")) != utility::string_t::npos ) +//unsigned int semanticType (const std::string &semantic) { +// static std::map semanticTypes ; +// if ( semantic.find (("TEXCOORD")) != std::string::npos ) // return (IOglTF::FLOAT_VEC2) ; -// if ( semantic.find (U("COLOR")) != utility::string_t::npos ) +// if ( semantic.find (("COLOR")) != std::string::npos ) // return (IOglTF::FLOAT_VEC4) ; // if ( semanticTypes.empty () ) { // // attributes -// semanticTypes [U("POSITION")] =IOglTF::FLOAT_VEC3 ; // Babylon.js does not like VEC4 -// semanticTypes [U("NORMAL")] =IOglTF::FLOAT_VEC3; -// semanticTypes [U("REFLECTIVE")] =IOglTF::FLOAT_VEC2 ; -// semanticTypes [U("WEIGHT")] =IOglTF::FLOAT_VEC4 ; -// semanticTypes [U("JOINT")] =IOglTF::FLOAT_VEC4 ; -// semanticTypes [U("TEXTANGENT")] =IOglTF::FLOAT_VEC3 ; -// semanticTypes [U("TEXBINORMAL")] =IOglTF::FLOAT_VEC3 ; +// semanticTypes [("POSITION")] =IOglTF::FLOAT_VEC3 ; // Babylon.js does not like VEC4 +// semanticTypes [("NORMAL")] =IOglTF::FLOAT_VEC3; +// semanticTypes [("REFLECTIVE")] =IOglTF::FLOAT_VEC2 ; +// semanticTypes [("WEIGHT")] =IOglTF::FLOAT_VEC4 ; +// semanticTypes [("JOINT")] =IOglTF::FLOAT_VEC4 ; +// semanticTypes [("TEXTANGENT")] =IOglTF::FLOAT_VEC3 ; +// semanticTypes [("TEXBINORMAL")] =IOglTF::FLOAT_VEC3 ; // // uniforms -// semanticTypes [U("MODELVIEWINVERSETRANSPOSE")] =IOglTF::FLOAT_MAT3 ; //typically the normal matrix -// semanticTypes [U("MODELVIEWINVERSE")]=IOglTF::FLOAT_MAT4 ; -// semanticTypes [U("MODELVIEW")] =IOglTF::FLOAT_MAT4 ; -// semanticTypes [U("PROJECTION")] =IOglTF::FLOAT_MAT4 ; -// semanticTypes [U("JOINTMATRIX")] =IOglTF::FLOAT_MAT4 ; +// semanticTypes [("MODELVIEWINVERSETRANSPOSE")] =IOglTF::FLOAT_MAT3 ; //typically the normal matrix +// semanticTypes [("MODELVIEWINVERSE")]=IOglTF::FLOAT_MAT4 ; +// semanticTypes [("MODELVIEW")] =IOglTF::FLOAT_MAT4 ; +// semanticTypes [("PROJECTION")] =IOglTF::FLOAT_MAT4 ; +// semanticTypes [("JOINTMATRIX")] =IOglTF::FLOAT_MAT4 ; // } // return (semanticTypes [semantic]) ; //} -//unsigned int semanticAttributeType (const utility::string_t &semantic) { -// static std::map semanticAttributeTypes ; -// if ( semantic.find (U("TEXCOORD")) != utility::string_t::npos ) +//unsigned int semanticAttributeType (const std::string &semantic) { +// static std::map semanticAttributeTypes ; +// if ( semantic.find (("TEXCOORD")) != std::string::npos ) // return (IOglTF::FLOAT_VEC2) ; -// if ( semantic.find (U("COLOR")) != utility::string_t::npos ) +// if ( semantic.find (("COLOR")) != std::string::npos ) // return (IOglTF::FLOAT_VEC4) ; // if ( semanticAttributeTypes.empty () ) { -// semanticAttributeTypes [U("POSITION")] =IOglTF::FLOAT_VEC3 ; -// semanticAttributeTypes [U("NORMAL")] =IOglTF::FLOAT_VEC3; -// semanticAttributeTypes [U("REFLECTIVE")] =IOglTF::FLOAT_VEC2 ; -// semanticAttributeTypes [U("WEIGHT")] =IOglTF::FLOAT_VEC4 ; -// semanticAttributeTypes [U("JOINT")] =IOglTF::FLOAT_VEC4 ; -// semanticAttributeTypes [U("TEXTANGENT")] =IOglTF::FLOAT_VEC3 ; -// semanticAttributeTypes [U("TEXBINORMAL")] =IOglTF::FLOAT_VEC3 ; +// semanticAttributeTypes [("POSITION")] =IOglTF::FLOAT_VEC3 ; +// semanticAttributeTypes [("NORMAL")] =IOglTF::FLOAT_VEC3; +// semanticAttributeTypes [("REFLECTIVE")] =IOglTF::FLOAT_VEC2 ; +// semanticAttributeTypes [("WEIGHT")] =IOglTF::FLOAT_VEC4 ; +// semanticAttributeTypes [("JOINT")] =IOglTF::FLOAT_VEC4 ; +// semanticAttributeTypes [("TEXTANGENT")] =IOglTF::FLOAT_VEC3 ; +// semanticAttributeTypes [("TEXBINORMAL")] =IOglTF::FLOAT_VEC3 ; // } // return (semanticAttributeTypes [semantic]) ; //} // -//unsigned int semanticUniformType (const utility::string_t &semantic) { -// static std::map semanticUniformTypes ; +//unsigned int semanticUniformType (const std::string &semantic) { +// static std::map semanticUniformTypes ; // if ( semanticUniformTypes.empty () ) { -// semanticUniformTypes [U("MODELVIEWINVERSETRANSPOSE")] =IOglTF::FLOAT_MAT3 ; //typically the normal matrix -// semanticUniformTypes [U("MODELVIEWINVERSE")]=IOglTF::FLOAT_MAT4 ; -// semanticUniformTypes [U("MODELVIEW")] =IOglTF::FLOAT_MAT4 ; -// semanticUniformTypes [U("PROJECTION")] =IOglTF::FLOAT_MAT4 ; -// semanticUniformTypes [U("JOINTMATRIX")] =IOglTF::FLOAT_MAT4 ; +// semanticUniformTypes [("MODELVIEWINVERSETRANSPOSE")] =IOglTF::FLOAT_MAT3 ; //typically the normal matrix +// semanticUniformTypes [("MODELVIEWINVERSE")]=IOglTF::FLOAT_MAT4 ; +// semanticUniformTypes [("MODELVIEW")] =IOglTF::FLOAT_MAT4 ; +// semanticUniformTypes [("PROJECTION")] =IOglTF::FLOAT_MAT4 ; +// semanticUniformTypes [("JOINTMATRIX")] =IOglTF::FLOAT_MAT4 ; // } // return (semanticUniformTypes [semantic]) ; //} @@ -656,13 +649,13 @@ void glslTech::finalizingShaders (web::json::value technique, web::json::value g //} ; // //bool addSemantic (glslShader &shader, parameterContext attributeOrUniform, -// utility::string_t semantic, -// utility::string_t parameterID, +// std::string semantic, +// std::string parameterID, // size_t count, // bool includesVarying, // bool forcesAsAnArray =false) { // -// utility::string_t symbol =(attributeOrUniform ? U("a_") : U("u_")) + parameterID ; +// std::string symbol =(attributeOrUniform ? ("a_") : ("u_")) + parameterID ; // unsigned int type =semanticType (semantic) ; // shared_ptr parameter (new GLTF::JSONObject ()); // parameter->setString (kSemantic, semantic); diff --git a/IO-glTF/glslShader.h b/IO-glTF/glslShader.h index 2ee45ef..8934369 100644 --- a/IO-glTF/glslShader.h +++ b/IO-glTF/glslShader.h @@ -28,32 +28,31 @@ namespace _IOglTF_NS_ { class glslShader { protected: - utility::string_t _name ; - utility::string_t _declarations ; - utility::string_t _body ; - std::map _allSymbols ; + std::string _name ; + std::string _declarations ; + std::string _body ; + std::map _allSymbols ; public: - glslShader (const utility::char_t *glslVersion =nullptr) ; + glslShader (const char *glslVersion =nullptr) ; virtual ~glslShader () ; - utility::string_t &name () ; + std::string &name () ; protected: - void _addDeclaration (utility::string_t qualifier, utility::string_t symbol, unsigned int type, size_t count, bool forcesAsAnArray =false) ; - utility::string_t body () ; + void _addDeclaration (std::string qualifier, std::string symbol, unsigned int type, size_t count, bool forcesAsAnArray =false) ; + std::string body () ; public: - void addAttribute (utility::string_t symbol, unsigned int type, size_t count =1, bool forcesAsAnArray =false) ; - void addUniform (utility::string_t symbol, unsigned int type, size_t count =1, bool forcesAsAnArray =false) ; - void addVarying (utility::string_t symbol, unsigned int type, size_t count =1, bool forcesAsAnArray =false) ; - bool hasSymbol (const utility::string_t &symbol) ; + void addAttribute (std::string symbol, unsigned int type, size_t count =1, bool forcesAsAnArray =false) ; + void addUniform (std::string symbol, unsigned int type, size_t count =1, bool forcesAsAnArray =false) ; + void addVarying (std::string symbol, unsigned int type, size_t count =1, bool forcesAsAnArray =false) ; + bool hasSymbol (const std::string &symbol) ; void appendCode (const char *format, ...) ; - void appendCode (const utility::char_t *format, ...) ; - //void appendCode (const utility::char_t *code) ; - utility::string_t source () ; + //void appendCode (const char *code) ; + std::string source () ; - static bool isVertexShaderSemantic (const utility::char_t *semantic) ; - static bool isFragmentShaderSemantic (const utility::char_t *semantic) ; + static bool isVertexShaderSemantic (const char *semantic) ; + static bool isFragmentShaderSemantic (const char *semantic) ; } ; @@ -75,24 +74,24 @@ class glslTech { glslShader _fragmentShader ; public: - glslTech (web::json::value technique, web::json::value values, web::json::value gltf, const utility::char_t *glslVersion =nullptr) ; + glslTech (Json::Value technique, Json::Value values, Json::Value gltf, const char *glslVersion =nullptr) ; virtual ~glslTech () ; glslShader &vertexShader () { return (_vertexShader) ; } glslShader &fragmentShader () { return (_fragmentShader) ; } protected: - static utility::string_t format (const utility::char_t *format, ...) ; - const utility::string_t needsVarying (const utility::char_t *semantic) ; - static bool isVertexShaderSemantic (const utility::char_t *semantic) ; - static bool isFragmentShaderSemantic (const utility::char_t *semantic) ; - void prepareParameters (web::json::value technique) ; + static std::string format (const char *format, ...) ; + const std::string needsVarying (const char *semantic) ; + static bool isVertexShaderSemantic (const char *semantic) ; + static bool isFragmentShaderSemantic (const char *semantic) ; + void prepareParameters (Json::Value technique) ; void hwSkinning () ; - bool lighting1 (web::json::value technique, web::json::value gltf) ; - void texcoords (web::json::value technique) ; - web::json::value lightNodes (web::json::value gltf) ; - void lighting2 (web::json::value technique, web::json::value gltf) ; - void finalizingShaders (web::json::value technique, web::json::value gltf) ; + bool lighting1 (Json::Value technique, Json::Value gltf) ; + void texcoords (Json::Value technique) ; + Json::Value lightNodes (Json::Value gltf) ; + void lighting2 (Json::Value technique, Json::Value gltf) ; + void finalizingShaders (Json::Value technique, Json::Value gltf) ; } ; diff --git a/IO-glTF/gltfWriter-Asset.cpp b/IO-glTF/gltfWriter-Asset.cpp index 1f31db2..62d0db7 100644 --- a/IO-glTF/gltfWriter-Asset.cpp +++ b/IO-glTF/gltfWriter-Asset.cpp @@ -24,7 +24,7 @@ namespace _IOglTF_NS_ { bool gltfWriter::WriteAsset (FbxDocumentInfo *pSceneInfo) { - web::json::value asset =web::json::value::object () ; + Json::Value asset ; // unit - and . In FBX we always work in centimeters, but we already converted to meter here //double scale =_scene->GetGlobalSettings ().GetSystemUnit ().GetScaleFactor () / 100. ; @@ -34,20 +34,18 @@ bool gltfWriter::WriteAsset (FbxDocumentInfo *pSceneInfo) { //FbxAxisSystem axisSystem =pScene->GetGlobalSettings ().GetAxisSystem () ; // FBX uses author and comments, not authoring_tool(i.e. generator), and copyright. - asset [U("copyright")] =web::json::value::string (utility::conversions::to_string_t (pSceneInfo->mAuthor.Buffer ())) ; - asset [U("generator")] =web::json::value::string (FBX_GLTF_EXPORTER) ; + asset [("copyright")] =(pSceneInfo->mAuthor.Buffer ()) ; + asset [("generator")] =(FBX_GLTF_EXPORTER) ; if ( _writeDefaults ) - asset [U ("premultipliedAlpha")] =web::json::value::boolean (false) ; + asset [("premultipliedAlpha")] =(false) ; if (_writeDefaults) { - asset[U("profile")] = web::json::value::object({ - { U("api"), web::json::value::string (PROFILE_API) }, // default "WebGL" - { U("version"), web::json::value::string (PROFILE_VERSION) } } // default 1.0.3 - ) ; + asset[("profile")]["api"] =(PROFILE_API) ; // default "WebGL" + asset[("profile")]["version"] =(PROFILE_VERSION) ; // default 1.0.3 } - asset [U("version")] =web::json::value::string (GLTF_VERSION) ; + asset [("version")] =(GLTF_VERSION) ; - _json [U("asset")] =asset ; + _json [("asset")] =asset ; return (true) ; } diff --git a/IO-glTF/gltfWriter-Buffer.cpp b/IO-glTF/gltfWriter-Buffer.cpp index 950f0d9..ff4f67a 100644 --- a/IO-glTF/gltfWriter-Buffer.cpp +++ b/IO-glTF/gltfWriter-Buffer.cpp @@ -24,22 +24,22 @@ namespace _IOglTF_NS_ { bool gltfWriter::WriteBuffer () { - web::json::value buffer =web::json::value::object () ; - FbxString filename =FbxPathUtils::GetFileName (utility::conversions::to_utf8string (_fileName).c_str (), false) ; - buffer [U("name")] =web::json::value::string (utility::conversions::to_string_t (filename.Buffer ())) ; + Json::Value buffer ; + FbxString filename =FbxPathUtils::GetFileName ((_fileName).c_str (), false) ; + buffer [("name")] =filename.Buffer () ; - buffer [U("uri")] =web::json::value::string (utility::conversions::to_string_t ((filename + ".bin").Buffer ())) ; + buffer [("uri")] =(filename + ".bin").Buffer () ; // The Buffer file should be fully completed by now. if ( GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_EMBEDMEDIA, false) ) { // data:[][;charset=][;base64], - buffer [U("uri")] =web::json::value::string (IOglTF::dataURI (_bin)) ; + buffer [("uri")] =IOglTF::dataURI (_bin) ; } if ( _writeDefaults ) - buffer [U("type")] =web::json::value::string (U("arraybuffer")) ; ; // default is arraybuffer - buffer [U("byteLength")] =web::json::value::number ((int)_bin.tellg ()) ; + buffer [("type")] =("arraybuffer") ; ; // default is arraybuffer + buffer [("byteLength")] =((int)_bin.tellg ()) ; - _json [U("buffers")] [utility::conversions::to_string_t (filename.Buffer ())] =buffer ; + _json [("buffers")] [filename.Buffer ()] =buffer ; return (true) ; } diff --git a/IO-glTF/gltfWriter-Camera.cpp b/IO-glTF/gltfWriter-Camera.cpp index 4dd2868..b9b8dd9 100644 --- a/IO-glTF/gltfWriter-Camera.cpp +++ b/IO-glTF/gltfWriter-Camera.cpp @@ -75,15 +75,16 @@ double gltfWriter::cameraYFOV (FbxCamera *pCamera) { return (focalAngle) ; } -web::json::value gltfWriter::WriteCamera (FbxNode *pNode) { - web::json::value camera =web::json::value::object () ; - web::json::value cameraDef =web::json::value::object () ; - camera [U("name")] =web::json::value::string (nodeId (pNode, true)) ; +Json::Value gltfWriter::WriteCamera (FbxNode *pNode) { + Json::Value camera; + Json::Value cameraDef; + camera [("name")] =nodeId (pNode, true) ; if ( isKnownId (pNode->GetNodeAttribute ()->GetUniqueID ()) ) { // The camera was already exported, create only the transform node - web::json::value node =WriteNode (pNode) ; - web::json::value ret =web::json::value::object ({ { U("nodes"), node } }) ; + Json::Value node =WriteNode (pNode) ; + Json::Value ret; + ret[("nodes")] = node ; return (ret) ; } @@ -91,32 +92,35 @@ web::json::value gltfWriter::WriteCamera (FbxNode *pNode) { //FbxCamera::EAspectRatioMode aspectRatioMode =pCamera->GetAspectRatioMode () ; switch ( pCamera->ProjectionType.Get () ) { case FbxCamera::EProjectionType::ePerspective: - camera [U("type")] =web::json::value::string (U("perspective")) ; - cameraDef [U("aspectRatio")] =web::json::value::number (pCamera->FilmAspectRatio) ; // (pCamera->AspectWidth / pCamera->AspectHeight) ; - //cameraDef [U("yfov")] =web::json::value::number (DEG2RAD(pCamera->FieldOfView)) ; - cameraDef [U("yfov")] =web::json::value::number (GLTF_ANGLE (cameraYFOV (pCamera))) ; - cameraDef [U("zfar")] =web::json::value::number (pCamera->FarPlane) ; - cameraDef [U("znear")] =web::json::value::number (pCamera->NearPlane) ; - camera [U("perspective")] =cameraDef ; + camera [("type")] =(("perspective")) ; + cameraDef [("aspectRatio")] =(pCamera->FilmAspectRatio.Get()) ; // (pCamera->AspectWidth / pCamera->AspectHeight) ; + //cameraDef [("yfov")] =(DEG2RAD(pCamera->FieldOfView)) ; + cameraDef [("yfov")] =(GLTF_ANGLE (cameraYFOV (pCamera))) ; + cameraDef [("zfar")] =(pCamera->FarPlane.Get()) ; + cameraDef [("znear")] =(pCamera->NearPlane.Get()) ; + camera [("perspective")] =cameraDef ; break ; case FbxCamera::EProjectionType::eOrthogonal: - camera [U("type")] =web::json::value::string (U("orthographic")) ; - //cameraDef [U("xmag")] =web::json::value::number (pCamera->_2DMagnifierX) ; - //cameraDef [U("ymag")] =web::json::value::number (pCamera->_2DMagnifierY) ; - cameraDef [U("xmag")] =web::json::value::number (pCamera->OrthoZoom) ; - cameraDef [U("ymag")] =web::json::value::number (pCamera->OrthoZoom) ; // FBX Collada reader set OrthoZoom using xmag and ymag each time they appear - cameraDef [U("zfar")] =web::json::value::number (pCamera->FarPlane) ; - cameraDef [U("znear")] =web::json::value::number (pCamera->NearPlane) ; - camera [U("orthographic")] =cameraDef ; + camera [("type")] =(("orthographic")) ; + //cameraDef [("xmag")] =(pCamera->_2DMagnifierX) ; + //cameraDef [("ymag")] =(pCamera->_2DMagnifierY) ; + cameraDef [("xmag")] =(pCamera->OrthoZoom.Get()) ; + cameraDef [("ymag")] =(pCamera->OrthoZoom.Get()) ; // FBX Collada reader set OrthoZoom using xmag and ymag each time they appear + cameraDef [("zfar")] =(pCamera->FarPlane.Get()) ; + cameraDef [("znear")] =(pCamera->NearPlane.Get()) ; + camera [("orthographic")] =cameraDef ; break ; default: _ASSERTE (false) ; break ; } - web::json::value lib =web::json::value::object ({ { nodeId (pNode, true, true), camera } }) ; - web::json::value node =WriteNode (pNode) ; - - return (web::json::value::object ({ { U("cameras"), lib }, { U("nodes"), node } })) ; + Json::Value lib; + lib[nodeId (pNode, true, true)] = camera ; + Json::Value node =WriteNode (pNode) ; + Json::Value ret; + ret["cameras"] = lib; + ret["nodes"] = node; + return ret ; } } diff --git a/IO-glTF/gltfWriter-Light.cpp b/IO-glTF/gltfWriter-Light.cpp index b77d4a6..720aea9 100644 --- a/IO-glTF/gltfWriter-Light.cpp +++ b/IO-glTF/gltfWriter-Light.cpp @@ -23,7 +23,7 @@ namespace _IOglTF_NS_ { -void gltfWriter::lightAttenuation (FbxLight *pLight, web::json::value &lightDef) { +void gltfWriter::lightAttenuation (FbxLight *pLight, Json::Value &lightDef) { float attenuation [3] = { 1.f, // Constant 0.f, // Linear @@ -36,7 +36,7 @@ void gltfWriter::lightAttenuation (FbxLight *pLight, web::json::value &lightDef) break ; case FbxLight::EDecayType::eCubic: attenuation [0] =0.0f ; - attenuation [2] =1.0f ; // OpenGL doesn't support cubicU( so default to quadratic + attenuation [2] =1.0f ; // OpenGL doesn't support cubic( so default to quadratic break ; case FbxLight::EDecayType::eQuadratic: attenuation [0] =0.0f ; @@ -48,88 +48,94 @@ void gltfWriter::lightAttenuation (FbxLight *pLight, web::json::value &lightDef) break ; } if ( attenuation [0] != 1.0f ) - lightDef [U("constantAttenuation")] =web::json::value::number (attenuation [0]) ; + lightDef [("constantAttenuation")] =(attenuation [0]) ; if ( attenuation [1] != 0.0f ) - lightDef [U("linearAttenuation")] =web::json::value::number (attenuation [1]) ; + lightDef [("linearAttenuation")] =(attenuation [1]) ; if ( attenuation [2] != 0.0f ) - lightDef [U("quadraticAttenuation")] =web::json::value::number (attenuation [2]) ; + lightDef [("quadraticAttenuation")] =(attenuation [2]) ; } -web::json::value gltfWriter::WriteLight (FbxNode *pNode) { - web::json::value light =web::json::value::object () ; - web::json::value lightDef =web::json::value::object () ; - light [U("name")] =web::json::value::string (nodeId (pNode, true)) ; +Json::Value gltfWriter::WriteLight (FbxNode *pNode) { + Json::Value light ; + Json::Value lightDef ; + light [("name")] =nodeId (pNode, true) ; if ( isKnownId (pNode->GetNodeAttribute ()->GetUniqueID ()) ) { // The light was already exported, create only the transform node - web::json::value node =WriteNode (pNode) ; - web::json::value ret =web::json::value::object ({ { U("nodes"), node } }) ; + Json::Value node =WriteNode (pNode) ; + Json::Value ret; + ret["nodes"] = node ; return (ret) ; } FbxLight *pLight =pNode->GetLight () ; //FbxCast(pNode->GetNodeAttribute ()) ; static const FbxDouble3 defaultLightColor (1., 1., 1.) ; auto color =pLight->Color ; - if ( _writeDefaults || color.Get () != defaultLightColor ) - lightDef [U("color")] =web::json::value::array ({{ - static_cast(color.Get () [0]), - static_cast(color.Get () [1]), - static_cast(color.Get () [2]) - }}) ; + if ( _writeDefaults || color.Get () != defaultLightColor ) { + auto &lightColor = lightDef["color"]; + lightColor[0] = static_cast(color.Get () [0]); + lightColor[1] = static_cast(color.Get () [1]); + lightColor[2] = static_cast(color.Get () [2]); + } switch ( pLight->LightType.Get () ) { case FbxLight::EType::ePoint: - light [U("type")] =web::json::value::string (U("point")) ; + light [("type")] =(("point")) ; lightAttenuation (pLight, lightDef) ; - light [U("point")] =lightDef ; + light [("point")] =lightDef ; break ; case FbxLight::EType::eSpot: - light [U("type")] =web::json::value::string (U("spot")) ; + light [("type")] =(("spot")) ; lightAttenuation (pLight, lightDef) ; if ( pLight->OuterAngle.Get () != 180.0 ) // default is PI - lightDef [U("fallOffAngle")] =DEG2RAD (pLight->OuterAngle) ; + lightDef [("fallOffAngle")] =DEG2RAD (pLight->OuterAngle) ; if ( _writeDefaults ) - lightDef [U("fallOffExponent")] =web::json::value::number ((double)0.) ; - light [U("spot")] =lightDef ; + lightDef [("fallOffExponent")] =((double)0.) ; + light [("spot")] =lightDef ; break ; case FbxLight::EType::eDirectional: - light [U("type")] =web::json::value::string (U("directional")) ; - light [U("directional")] =lightDef ; + light [("type")] =(("directional")) ; + light [("directional")] =lightDef ; break ; case FbxLight::EType::eArea: case FbxLight::EType::eVolume: default: // ambient _ASSERTE (false) ; - return (web::json::value::object ()) ; + return (Json::Value()) ; break ; } - web::json::value lib =web::json::value::object ({ { nodeId (pNode, true, true), light } }) ; - web::json::value node =WriteNode (pNode) ; - - return (web::json::value::object ({ { U("lights"), lib }, { U("nodes"), node } })) ; + Json::Value lib ; + lib[nodeId (pNode, true, true)] = light ; + Json::Value node =WriteNode (pNode) ; + + Json::Value ret; + ret["lights"] = lib; + ret["nodes"] = node; + return ret ; } -web::json::value gltfWriter::WriteAmbientLight (FbxScene &pScene) { - web::json::value light =web::json::value::object () ; - web::json::value lightDef =web::json::value::object () ; +Json::Value gltfWriter::WriteAmbientLight (FbxScene &pScene) { + Json::Value light ; + Json::Value lightDef ; static const FbxDouble3 defaultLightColor (1., 1., 1.) ; FbxColor color (pScene.GetGlobalSettings ().GetAmbientColor ()) ; if ( !color.mRed && !color.mGreen && !color.mBlue ) - return (web::json::value::object ()) ; + return (Json::Value()) ; if ( !_writeDefaults && color == defaultLightColor ) - return (web::json::value::object ()) ; - lightDef [U("color")] =web::json::value::array () ; - lightDef [U("color")] [0] =static_cast (color.mRed) ; - lightDef [U("color")] [1] =static_cast (color.mGreen) ; - lightDef [U("color")] [2] =static_cast (color.mBlue) ; - light [U("type")] =web::json::value::string (U("ambient")) ; - light [U("ambient")] =lightDef ; + return (Json::Value()) ; + lightDef [("color")] [0] =static_cast (color.mRed) ; + lightDef [("color")] [1] =static_cast (color.mGreen) ; + lightDef [("color")] [2] =static_cast (color.mBlue) ; + light [("type")] =(("ambient")) ; + light [("ambient")] =lightDef ; - utility::string_t buffer =utility::conversions::to_string_t ((int)0) ; - utility::string_t uid (U("defaultambient")) ; - uid +=U("_") + buffer ; - return (web::json::value::object ({ { uid, light } })) ; - //return (web::json::value::object ({ { nodeId (U("defaultambient"), 0x00), light } })) ; + std::string buffer =utility::conversions::to_string_t ((int)0) ; + std::string uid (("defaultambient")) ; + uid +=("_") + buffer ; + Json::Value ret; + ret[uid] = light; + return ret ; + //return (Json::Value::object ({ { nodeId (("defaultambient"), 0x00), light } })) ; } } \ No newline at end of file diff --git a/IO-glTF/gltfWriter-Line.cpp b/IO-glTF/gltfWriter-Line.cpp index 8be8487..4344326 100644 --- a/IO-glTF/gltfWriter-Line.cpp +++ b/IO-glTF/gltfWriter-Line.cpp @@ -77,29 +77,29 @@ FbxArray GetVertexPositions (FbxLine *pLine, bool bInGeometry =true, } //----------------------------------------------------------------------------- -web::json::value gltfWriter::WriteLine (FbxNode *pNode) { +Json::Value gltfWriter::WriteLine (FbxNode *pNode) { #ifdef GG - web::json::value lineDef =web::json::value::object () ; - lineDef [U("name")] =web::json::value::string (nodeId (pNode, true)) ; + Json::Value lineDef ; + lineDef [("name")] =(nodeId (pNode, true)) ; if ( isKnownId (pNode->GetNodeAttribute ()->GetUniqueID ()) ) { // The line/material/... were already exported, create only the transform node - web::json::value node =WriteNode (pNode) ; - web::json::value ret =web::json::value::object ({ { U("nodes"), node } }) ; + Json::Value node =WriteNode (pNode) ; + Json::Value ret =Json::Value::object ({ { ("nodes"), node } }) ; return (ret) ; } - web::json::value linePrimitives =web::json::value::array () ; - web::json::value accessorsAndBufferViews =web::json::value::object ({ - { U("accessors"), web::json::value::object () }, - { U("bufferViews"), web::json::value::object () } + Json::Value linePrimitives =Json::Value::array () ; + Json::Value accessorsAndBufferViews =Json::Value::object ({ + { ("accessors"), Json::Value::object () }, + { ("bufferViews"), Json::Value::object () } }) ; - web::json::value materials =web::json::value::object ({ { U("materials"), web::json::value::object () } }) ; - web::json::value techniques =web::json::value::object ({ { U("techniques"), web::json::value::object () } }) ; - web::json::value programs =web::json::value::object ({ { U("programs"), web::json::value::object () } }) ; - web::json::value images =web::json::value::object ({ { U("images"), web::json::value::object () } }) ; - web::json::value samplers =web::json::value::object ({ { U("samplers"), web::json::value::object () } }) ; - web::json::value textures =web::json::value::object ({ { U("textures"), web::json::value::object () } }) ; + Json::Value materials =Json::Value::object ({ { ("materials"), Json::Value::object () } }) ; + Json::Value techniques =Json::Value::object ({ { ("techniques"), Json::Value::object () } }) ; + Json::Value programs =Json::Value::object ({ { ("programs"), Json::Value::object () } }) ; + Json::Value images =Json::Value::object ({ { ("images"), Json::Value::object () } }) ; + Json::Value samplers =Json::Value::object ({ { ("samplers"), Json::Value::object () } }) ; + Json::Value textures =Json::Value::object ({ { ("textures"), Json::Value::object () } }) ; FbxLine *pLine =pNode->GetLine () ; //FbxCast(pNode->GetNodeAttribute ()) ; pLine->ComputeBBox () ; @@ -119,12 +119,12 @@ web::json::value gltfWriter::WriteLine (FbxNode *pNode) { // - Warnings for unsupported layer element types: polygon groups, undefined int nbLayers =pLine->GetLayerCount () ; - web::json::value primitive=web::json::value::object ({ - { U("attributes"), web::json::value::object () }, - { U("mode"), IOglTF::LINES } // Allowed values are 0 (POINTS), 1 (LINES), 2 (LINE_LOOP), 3 (LINE_STRIP), 4 (TRIANGLES), 5 (TRIANGLE_STRIP), and 6 (TRIANGLE_FAN). + Json::Value primitive=Json::Value::object ({ + { ("attributes"), Json::Value::object () }, + { ("mode"), IOglTF::LINES } // Allowed values are 0 (POINTS), 1 (LINES), 2 (LINE_LOOP), 3 (LINE_STRIP), 4 (TRIANGLES), 5 (TRIANGLE_STRIP), and 6 (TRIANGLE_FAN). }) ; - web::json::value localAccessorsAndBufferViews =web::json::value::object () ; + Json::Value localAccessorsAndBufferViews ; int deformerCount =pLine->GetDeformerCount (FbxDeformer::eSkin) ; _ASSERTE (deformerCount <= 1) ; // "Unexpected number of skin greater than 1") ; @@ -136,13 +136,13 @@ web::json::value gltfWriter::WriteLine (FbxNode *pNode) { // std::vector out_positions =vbo.getPositions () ; - web::json::value vertex =WriteArrayWithMinMax (out_positions, pLine->GetNode (), U("_Positions")) ; + Json::Value vertex =WriteArrayWithMinMax (out_positions, pLine->GetNode (), ("_Positions")) ; MergeJsonObjects (localAccessorsAndBufferViews, vertex); - primitive [U("attributes")] [U("POSITION")] =web::json::value::string (GetJsonFirstKey (vertex [U("accessors")])) ; + primitive [("attributes")] [("POSITION")] =(GetJsonFirstKey (vertex [("accessors")])) ; // Get line face indices - web::json::value polygons =WriteArray (out_indices, 1, pLine->GetNode (), U("_Polygons")) ; - primitive [U("indices")] =web::json::value::string (GetJsonFirstKey (polygons [U("accessors")])) ; + Json::Value polygons =WriteArray (out_indices, 1, pLine->GetNode (), ("_Polygons")) ; + primitive [("indices")] =(GetJsonFirstKey (polygons [("accessors")])) ; MergeJsonObjects (accessorsAndBufferViews, polygons) ; MergeJsonObjects (accessorsAndBufferViews, localAccessorsAndBufferViews) ; @@ -150,30 +150,30 @@ web::json::value gltfWriter::WriteLine (FbxNode *pNode) { // Get material FbxLayer *pLayer =gltfwriterVBO::getLayer (pLine, FbxLayerElement::eMaterial) ; if ( pLayer == nullptr ) { - //ucout << U("Info: (") << utility::conversions::to_string_t (pNode->GetTypeName ()) - // << U(") ") << utility::conversions::to_string_t (pNode->GetName ()) - // << U(" no material on Layer: ") + //std::cout << ("Info: (") << utility::conversions::to_string_t (pNode->GetTypeName ()) + // << (") ") << utility::conversions::to_string_t (pNode->GetName ()) + // << (" no material on Layer: ") // << iLayer // << std::endl ; // Create default material - web::json::value ret =WriteDefaultMaterial (pNode) ; + Json::Value ret =WriteDefaultMaterial (pNode) ; if ( ret.is_string () ) { - primitive [U("material")] =ret ; + primitive [("material")] =ret ; } else { - primitive [U("material")]=web::json::value::string (GetJsonFirstKey (ret [U("materials")])) ; + primitive [("material")]=(GetJsonFirstKey (ret [("materials")])) ; - MergeJsonObjects (materials [U("materials")], ret [U("materials")]) ; + MergeJsonObjects (materials [("materials")], ret [("materials")]) ; - utility::string_t techniqueName =GetJsonFirstKey (ret [U("techniques")]) ; - web::json::value techniqueParameters =ret [U("techniques")] [techniqueName] [U("parameters")] ; + std::string techniqueName =GetJsonFirstKey (ret [("techniques")]) ; + Json::Value techniqueParameters =ret [("techniques")] [techniqueName] [("parameters")] ; AdditionalTechniqueParameters (pNode, techniqueParameters, out_normals.size () != 0) ; - TechniqueParameters (pNode, techniqueParameters, primitive [U("attributes")], localAccessorsAndBufferViews [U("accessors")], false) ; + TechniqueParameters (pNode, techniqueParameters, primitive [("attributes")], localAccessorsAndBufferViews [("accessors")], false) ; ret =WriteTechnique (pNode, nullptr, techniqueParameters) ; //MergeJsonObjects (techniques, ret) ; - techniques [U("techniques")] [techniqueName] =ret ; + techniques [("techniques")] [techniqueName] =ret ; - utility::string_t programName =ret [U("program")].as_string () ; - web::json::value attributes =ret [U("attributes")] ; + std::string programName =ret [("program")].asString () ; + Json::Value attributes =ret [("attributes")] ; ret =WriteProgram (pNode, nullptr, programName, attributes) ; MergeJsonObjects (programs, ret) ; } @@ -182,53 +182,53 @@ web::json::value gltfWriter::WriteLine (FbxNode *pNode) { int materialCount =pLayerElementMaterial ? pNode->GetMaterialCount () : 0 ; if ( materialCount > 1 ) { _ASSERTE( materialCount > 1 ) ; - ucout << U("Warning: (") << utility::conversions::to_string_t (pNode->GetTypeName ()) - << U(") ") << utility::conversions::to_string_t (pNode->GetName ()) - << U(" got more than one material. glTF supports one material per primitive (FBX Layer).") + std::cout << ("Warning: (") << utility::conversions::to_string_t (pNode->GetTypeName ()) + << (") ") << utility::conversions::to_string_t (pNode->GetName ()) + << (" got more than one material. glTF supports one material per primitive (FBX Layer).") << std::endl ; } // TODO: need to be revisited when glTF will support more than one material per layer/primitive materialCount =materialCount == 0 ? 0 : 1 ; for ( int i =0 ; i < materialCount ; i++ ) { - web::json::value ret =WriteMaterial (pNode, pNode->GetMaterial (i)) ; + Json::Value ret =WriteMaterial (pNode, pNode->GetMaterial (i)) ; if ( ret.is_string () ) { - primitive [U("material")] =ret ; + primitive [("material")] =ret ; continue ; } - primitive [U("material")]=web::json::value::string (GetJsonFirstKey (ret [U("materials")])) ; - - MergeJsonObjects (materials [U("materials")], ret [U("materials")]) ; - if ( ret.has_field (U("images")) ) - MergeJsonObjects (images [U("images")], ret [U("images")]) ; - if ( ret.has_field (U("samplers")) ) - MergeJsonObjects (samplers [U("samplers")], ret [U("samplers")]) ; - if ( ret.has_field (U("textures")) ) - MergeJsonObjects (textures [U("textures")], ret [U("textures")]) ; - - utility::string_t techniqueName =GetJsonFirstKey (ret [U("techniques")]) ; - web::json::value techniqueParameters =ret [U("techniques")] [techniqueName] [U("parameters")] ; + primitive [("material")]=(GetJsonFirstKey (ret [("materials")])) ; + + MergeJsonObjects (materials [("materials")], ret [("materials")]) ; + if ( ret.isMember (("images")) ) + MergeJsonObjects (images [("images")], ret [("images")]) ; + if ( ret.isMember (("samplers")) ) + MergeJsonObjects (samplers [("samplers")], ret [("samplers")]) ; + if ( ret.isMember (("textures")) ) + MergeJsonObjects (textures [("textures")], ret [("textures")]) ; + + std::string techniqueName =GetJsonFirstKey (ret [("techniques")]) ; + Json::Value techniqueParameters =ret [("techniques")] [techniqueName] [("parameters")] ; AdditionalTechniqueParameters (pNode, techniqueParameters, out_normals.size () != 0) ; - TechniqueParameters (pNode, techniqueParameters, primitive [U("attributes")], localAccessorsAndBufferViews [U("accessors")]) ; + TechniqueParameters (pNode, techniqueParameters, primitive [("attributes")], localAccessorsAndBufferViews [("accessors")]) ; ret =WriteTechnique (pNode, pNode->GetMaterial (i), techniqueParameters) ; //MergeJsonObjects (techniques, ret) ; - techniques [U("techniques")] [techniqueName] =ret ; + techniques [("techniques")] [techniqueName] =ret ; - utility::string_t programName =ret [U("program")].as_string () ; - web::json::value attributes =ret [U("attributes")] ; + std::string programName =ret [("program")].asString () ; + Json::Value attributes =ret [("attributes")] ; ret =WriteProgram (pNode, pNode->GetMaterial (i), programName, attributes) ; MergeJsonObjects (programs, ret) ; } } linePrimitives [linePrimitives.size ()] =primitive ; - lineDef [U("primitives")] =linePrimitives ; + lineDef [("primitives")] =linePrimitives ; - web::json::value lib =web::json::value::object ({ { nodeId (pNode, true, true), lineDef } }) ; + Json::Value lib =Json::Value::object ({ { nodeId (pNode, true, true), lineDef } }) ; - web::json::value node =WriteNode (pNode) ; + Json::Value node =WriteNode (pNode) ; //if ( pLine->GetShapeCount () ) // WriteControllerShape (pLine) ; // Create a controller - web::json::value ret =web::json::value::object ({ { U("meshes"), lib }, { U("nodes"), node } }) ; + Json::Value ret =Json::Value::object ({ { ("meshes"), lib }, { ("nodes"), node } }) ; MergeJsonObjects (ret, accessorsAndBufferViews) ; MergeJsonObjects (ret, images) ; MergeJsonObjects (ret, materials) ; @@ -238,7 +238,7 @@ web::json::value gltfWriter::WriteLine (FbxNode *pNode) { MergeJsonObjects (ret, textures) ; return (ret) ; #else - return (web::json::value::null ()) ; + return (Json::Value::null ()) ; #endif } #endif diff --git a/IO-glTF/gltfWriter-Material.cpp b/IO-glTF/gltfWriter-Material.cpp index 5da6934..ecd9528 100644 --- a/IO-glTF/gltfWriter-Material.cpp +++ b/IO-glTF/gltfWriter-Material.cpp @@ -24,37 +24,37 @@ namespace _IOglTF_NS_ { // FBX does not support Blinn yet, it would become Phong by default. -utility::string_t gltfWriter::LighthingModel (FbxSurfaceMaterial *pMaterial) { +std::string gltfWriter::LighthingModel (FbxSurfaceMaterial *pMaterial) { if ( pMaterial->Is () ) { - return (U("Phong")) ; + return (("Phong")) ; } else if ( pMaterial->Is () ) { - return (U("Lambert")) ; + return (("Lambert")) ; } else { // use shading model FbxString szShadingModel =pMaterial->ShadingModel.Get () ; // shading models supported here are: "constant", "blinn" // note that "lambert" and "phong" should have been treated above // all others default to "phong" if ( szShadingModel == "constant" ) - return (U("Constant")) ; + return (("Constant")) ; else if ( szShadingModel == "blinn" ) - return (U("Blinn")) ; + return (("Blinn")) ; else - return (U("Phong")) ; + return (("Phong")) ; } } -web::json::value gltfWriter::WriteMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { - utility::string_t materialName =utility::conversions::to_string_t (pMaterial->GetNameWithoutNameSpacePrefix ().Buffer ()) ; // Material do not support namespaces. +Json::Value gltfWriter::WriteMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { + std::string materialName =pMaterial->GetNameWithoutNameSpacePrefix ().Buffer () ; // Material do not support namespaces. // Look if this material is already in the materials library. - //if ( _json [U("materials")].has_field (materialName) ) + //if ( _json [("materials")].isMember (materialName) ) if ( isNameRegistered (materialName) ) - return (web::json::value::string (materialName)) ; + return (Json::Value(materialName)) ; - web::json::value material =web::json::value::object () ; - material [U("name")] =web::json::value::string (materialName) ; + Json::Value material ; + material [("name")] =materialName ; - web::json::value ret =web::json::value::null () ; + Json::Value ret ; // Use Cg shaders in WebGL? // Usually you don't want to. @@ -113,69 +113,81 @@ web::json::value gltfWriter::WriteMaterial (FbxNode *pNode, FbxSurfaceMaterial * } - web::json::value techniqueParameters =web::json::value::null () ; - if ( !ret.is_null () ) { - material [U("values")] =ret [U("values")] ; - techniqueParameters =ret [U("techniqueParameters")] ; + Json::Value techniqueParameters ; + if ( !ret.isNull () ) { + material [("values")] =ret [("values")] ; + techniqueParameters =ret [("techniqueParameters")] ; } - utility::string_t techniqueName =createUniqueName (materialName + U("_technique"), 0) ; // Start with 0, but will increase based on own many are yet registered - material [U("technique")] =web::json::value::string (techniqueName) ; // technique name already registered + std::string techniqueName =createUniqueName (materialName + ("_technique"), 0) ; // Start with 0, but will increase based on own many are yet registered + material [("technique")] =(techniqueName) ; // technique name already registered registerName (materialName) ; // Register material name to avoid duplicates - web::json::value lib =web::json::value::object ({ { materialName, material } }) ; - - web::json::value technique =web::json::value::object ({{ U("parameters"), techniqueParameters }}) ; - web::json::value techniques =web::json::value::object ({ { techniqueName, technique } }) ; - - web::json::value full =web::json::value::object ({ { U("materials"), lib }, { U("techniques"), techniques } }) ; - if ( !ret.is_null () ) { - for ( auto iter =ret.as_object ().begin () ; iter != ret.as_object ().end () ; iter++ ) { - if ( iter->first != U("values") && iter->first != U("techniqueParameters") ) - full [iter->first] =iter->second ; + Json::Value lib; + lib[materialName] = material ; + + Json::Value technique ; + technique["parameters"] = techniqueParameters ; + Json::Value techniques ; + techniques[techniqueName] = technique ; + + Json::Value full ; + full[("materials")] = lib ; + full[("techniques")] = techniques ; + if ( !ret.isNull () ) { + auto memberNames = ret.getMemberNames(); + for ( auto &name : memberNames ) { + if ( name != ("values") && name != ("techniqueParameters") ) + full [name] =ret[name] ; } } return (full) ; } -web::json::value gltfWriter::WriteDefaultMaterial (FbxNode *pNode) { - utility::string_t materialName (U("defaultMaterial")) ; +Json::Value gltfWriter::WriteDefaultMaterial (FbxNode *pNode) { + std::string materialName (("defaultMaterial")) ; // Look if this material is already in the materials library. - //if ( _json [U("materials")].has_field (materialName) ) + //if ( _json [("materials")].isMember (materialName) ) if ( isNameRegistered (materialName) ) - return (web::json::value::string (materialName)) ; + return (Json::Value(materialName)) ; - web::json::value material =web::json::value::object () ; - material [U("name")] =web::json::value::string (materialName) ; + Json::Value material ; + material [("name")] =(materialName) ; // Look if this material is already in the materials library. - web::json::value ret =web::json::value::null () ; - if ( !_json [U("materials")].has_field (materialName) ) { + Json::Value ret ; + if ( !_json [("materials")].isMember (materialName) ) { FbxNode::EShadingMode shadingMode =pNode->GetShadingMode () ; ret =WriteDefaultShadingModelMaterial (pNode) ; } - web::json::value techniqueParameters =web::json::value::null () ; - if ( !ret.is_null () ) { - material [U("values")] =ret [U("values")] ; - techniqueParameters =ret [U("techniqueParameters")] ; + Json::Value techniqueParameters ; + if ( !ret.isNull () ) { + material [("values")] =ret [("values")] ; + techniqueParameters =ret [("techniqueParameters")] ; } - utility::string_t techniqueName =createUniqueName (materialName + U("_technique"), 0) ; // Start with 0, but will increase based on own many are yet registered - material [U("technique")] =web::json::value::string (techniqueName) ; // technique name already registered + std::string techniqueName =createUniqueName (materialName + ("_technique"), 0) ; // Start with 0, but will increase based on own many are yet registered + material [("technique")] =(techniqueName) ; // technique name already registered registerName (materialName) ; // Register material name to avoid duplicates - web::json::value lib =web::json::value::object ({ { materialName, material } }) ; - - web::json::value technique =web::json::value::object ({{ U("parameters"), techniqueParameters }}) ; - web::json::value techniques =web::json::value::object ({ { techniqueName, technique } }) ; - - web::json::value full =web::json::value::object ({ { U("materials"), lib }, { U("techniques"), techniques } }) ; - if ( !ret.is_null () ) { - for ( auto iter =ret.as_object ().begin () ; iter != ret.as_object ().end () ; iter++ ) { - if ( iter->first != U("values") && iter->first != U("techniqueParameters") ) - full [iter->first] =iter->second ; + Json::Value lib ; + lib[materialName] = material ; + + Json::Value technique ; + technique[("parameters")] = techniqueParameters ; + Json::Value techniques ; + techniques[techniqueName] = technique ; + + Json::Value full ; + full[("materials")] = lib ; + full[("techniques")] = techniques ; + if ( !ret.isNull () ) { + auto memberNames = ret.getMemberNames(); + for ( auto & name : memberNames ) { + if ( name != ("values") && name != ("techniqueParameters") ) + full [name] =ret[name] ; } } return (full) ; @@ -185,12 +197,12 @@ web::json::value gltfWriter::WriteDefaultMaterial (FbxNode *pNode) { // The transparency factor is usually in the range [0,1]. Maya does always export a transparency factor of 1.0, which implies full transparency. -web::json::value gltfWriter::WriteMaterialTransparencyParameter ( - const utility::char_t *pszName, +Json::Value gltfWriter::WriteMaterialTransparencyParameter ( + const char *pszName, FbxPropertyT &property, FbxPropertyT &propertyColor, FbxProperty &propertyOpaque, - web::json::value &values, web::json::value &techniqueParameters + Json::Value &values, Json::Value &techniqueParameters ) { - web::json::value ret =web::json::value::null () ; + Json::Value ret ; double value =1. ; if ( propertyOpaque.IsValid () ) { value =1.0 - propertyOpaque.Get () ; @@ -205,69 +217,73 @@ web::json::value gltfWriter::WriteMaterialTransparencyParameter ( } if ( !GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_INVERTTRANSPARENCY, false) ) value =1.0 - value ; - values [pszName] =web::json::value::number (value) ; - techniqueParameters [pszName] =web::json::value::object ({ { U("type"), IOglTF::FLOAT } }) ; + values [pszName] =(value) ; + techniqueParameters [pszName][("type")] = IOglTF::FLOAT ; return (ret) ; } -//web::json::value gltfWriter::WriteMaterialTransparencyParameter ( -// const utility::char_t *pszName, +//Json::Value gltfWriter::WriteMaterialTransparencyParameter ( +// const char *pszName, // FbxPropertyT &property, -// web::json::value &values, web::json::value &techniqueParameters +// Json::Value &values, Json::Value &techniqueParameters //) { -// web::json::value ret =web::json::value::null () ; +// Json::Value ret ; // if ( !property.IsValid () ) // return (ret) ; // double value =property.Get () ; // if ( !GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_INVERTTRANSPARENCY, false) ) // value =1.0 - value ; -// values [pszName] =web::json::value::number (value) ; -// techniqueParameters [pszName] =web::json::value::object ({ { U("type"), IOglTF::FLOAT } }) ; +// values [pszName] =(value) ; +// techniqueParameters [pszName] =Json::Value::object ({ { ("type"), IOglTF::FLOAT } }) ; // return (ret) ; //} -web::json::value gltfWriter::WriteMaterialParameter (const utility::char_t *pszName, FbxPropertyT &property, double factor, web::json::value &values, web::json::value &techniqueParameters) { - web::json::value ret =web::json::value::null () ; +Json::Value gltfWriter::WriteMaterialParameter (const char *pszName, FbxPropertyT &property, double factor, Json::Value &values, Json::Value &techniqueParameters) { + Json::Value ret ; if ( !property.IsValid () ) return (ret) ; if ( property.GetSrcObjectCount () != 0 ) { FbxTexture *pTexture =property.GetSrcObject (0) ; - values [pszName] =web::json::value::string (createTextureName (pTexture->GetName ())) ; - techniqueParameters [pszName] =web::json::value::object ({{ U("type"), IOglTF::SAMPLER_2D }}) ; + values [pszName] =(createTextureName (pTexture->GetName ())) ; + techniqueParameters [pszName] [("type")] = IOglTF::SAMPLER_2D ; ret =WriteTexture (pTexture) ; } else { FbxDouble3 color =property.Get () ; MultiplyDouble3By (color, factor) ; - values [pszName] =web::json::value::array ({ { color [0], color [1], color [2], 1. } }) ; - techniqueParameters [pszName] =web::json::value::object ({{ U("type"), IOglTF::FLOAT_VEC4 }}) ; + auto &colorVals = values [pszName]; + colorVals[0] = color [0]; + colorVals[1] = color [1]; + colorVals[2] = color [2]; + colorVals[3] = 1. ; + techniqueParameters [pszName] [("type")] = IOglTF::FLOAT_VEC4 ; } return (ret) ; } -web::json::value gltfWriter::WriteMaterialParameter (const utility::char_t *pszName, FbxPropertyT &property, web::json::value &values, web::json::value &techniqueParameters) { - web::json::value ret =web::json::value::null () ; +Json::Value gltfWriter::WriteMaterialParameter (const char *pszName, FbxPropertyT &property, Json::Value &values, Json::Value &techniqueParameters) { + Json::Value ret ; if ( !property.IsValid () ) return (ret) ; if ( property.GetSrcObjectCount () != 0 ) { FbxTexture *pTexture =property.GetSrcObject (0) ; - values [pszName] =web::json::value::string (createTextureName (pTexture->GetName ())) ; - techniqueParameters [pszName] =web::json::value::object ({ { U("type"), IOglTF::SAMPLER_2D } }) ; + values [pszName] =(createTextureName (pTexture->GetName ())) ; + techniqueParameters [pszName] [("type")] = IOglTF::SAMPLER_2D ; ret =WriteTexture (pTexture) ; } else { double value =property.Get () ; - values [pszName] =web::json::value::number (value) ; - techniqueParameters [pszName] =web::json::value::object ({ { U("type"), IOglTF::FLOAT } }) ; + values [pszName] =(value) ; + techniqueParameters [pszName] [("type")] = IOglTF::FLOAT ; } return (ret) ; } -web::json::value gltfWriter::WriteMaterialParameter (const utility::char_t *pszName, FbxSurfaceMaterial *pMaterial, const char *propertyName, const char *factorName, web::json::value &values, web::json::value &techniqueParameters) { - web::json::value ret =web::json::value::null () ; +Json::Value gltfWriter::WriteMaterialParameter (const char *pszName, FbxSurfaceMaterial *pMaterial, const char *propertyName, const char *factorName, Json::Value &values, Json::Value &techniqueParameters) { + Json::Value ret ; FbxProperty property =pMaterial->FindProperty (propertyName, FbxColor3DT, false) ; if ( property.IsValid () && property.GetSrcObjectCount () != 0 ) { FbxTexture *pTexture =property.GetSrcObject (0) ; - values [pszName] =web::json::value::string (createTextureName (pTexture->GetName ())) ; - techniqueParameters [pszName] =web::json::value::object ({{ U("type"), IOglTF::SAMPLER_2D }}) ; + values [pszName] =(createTextureName (pTexture->GetName ())) ; + techniqueParameters [pszName] [("type")] = IOglTF::SAMPLER_2D ; ret =WriteTexture (pTexture) ; } else { FbxProperty factorProperty =pMaterial->FindProperty (factorName, FbxDoubleDT, false) ; @@ -276,33 +292,38 @@ web::json::value gltfWriter::WriteMaterialParameter (const utility::char_t *pszN if ( !property.IsValid () && !factorProperty.IsValid () ) factor =0. ; MultiplyDouble3By (color, factor) ; - values [pszName] =web::json::value::array ({ { color [0], color [1], color [2], 1. } }) ; - techniqueParameters [pszName] =web::json::value::object ({{ U("type"), IOglTF::FLOAT_VEC4 }}) ; + auto &colorVals = values [pszName] ; + colorVals[0] = color [0]; + colorVals[1] = color [1]; + colorVals[2] = color [2]; + colorVals[3] = 1. ; + techniqueParameters [pszName] [("type")] = IOglTF::FLOAT_VEC4 ; } return (ret) ; } -web::json::value gltfWriter::WritePhongMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { - web::json::value values =web::json::value::object () ; - web::json::value techniqueParameters =web::json::value::object () ; +Json::Value gltfWriter::WritePhongMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { + Json::Value values ; + Json::Value techniqueParameters ; FbxSurfacePhong *pPhongSurface =FbxCast (pMaterial) ; - web::json::value ret =web::json::value::object () ; - MergeJsonObjects (ret, WriteMaterialParameter (U("ambient"), pPhongSurface->Ambient, pPhongSurface->AmbientFactor.Get (), values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("diffuse"), pPhongSurface->Diffuse, pPhongSurface->DiffuseFactor.Get (), values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("emission"), pPhongSurface->Emissive, pPhongSurface->EmissiveFactor.Get (), values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("specular"), pPhongSurface->Specular, pPhongSurface->SpecularFactor.Get (), values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("shininess"), pPhongSurface->Shininess, values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("reflective"), pPhongSurface->Reflection, 1., values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("reflectivity"), pPhongSurface->ReflectionFactor, values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("transparent"), pPhongSurface->TransparentColor, 1., values, techniqueParameters)) ; + Json::Value ret ; + MergeJsonObjects (ret, WriteMaterialParameter (("ambient"), pPhongSurface->Ambient, pPhongSurface->AmbientFactor.Get (), values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("diffuse"), pPhongSurface->Diffuse, pPhongSurface->DiffuseFactor.Get (), values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("emission"), pPhongSurface->Emissive, pPhongSurface->EmissiveFactor.Get (), values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("specular"), pPhongSurface->Specular, pPhongSurface->SpecularFactor.Get (), values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("shininess"), pPhongSurface->Shininess, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("reflective"), pPhongSurface->Reflection, 1., values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("reflectivity"), pPhongSurface->ReflectionFactor, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("transparent"), pPhongSurface->TransparentColor, 1., values, techniqueParameters)) ; // gltf - opaque is 1. / transparency is 0. // pPhongSurface->TransparentColor // Transparent color property. // pPhongSurface->TransparencyFactor // Transparency factor property. This property is used to make a surface more or less opaque (0 = opaque, 1 = transparent). + auto opacity = pPhongSurface->FindProperty ("Opacity"); MergeJsonObjects (ret, WriteMaterialTransparencyParameter ( - U("transparency"), - pPhongSurface->TransparencyFactor, pPhongSurface->TransparentColor, pPhongSurface->FindProperty ("Opacity"), + ("transparency"), + pPhongSurface->TransparencyFactor, pPhongSurface->TransparentColor, opacity, values, techniqueParameters )) ; @@ -314,168 +335,189 @@ web::json::value gltfWriter::WritePhongMaterial (FbxNode *pNode, FbxSurfaceMater // Note: // INDEXOFREFRACTION is not supported by FBX. - - MergeJsonObjects (ret, web::json::value::object ({ { U("values"), values }, { U("techniqueParameters"), techniqueParameters } })) ; + Json::Value temp; + temp["values"] = values; + temp["techniqueParameters"] = techniqueParameters; + MergeJsonObjects (ret, temp) ; return (ret) ; } -web::json::value gltfWriter::WriteLambertMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { - web::json::value values =web::json::value::object () ; - web::json::value techniqueParameters =web::json::value::object () ; +Json::Value gltfWriter::WriteLambertMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { + Json::Value values ; + Json::Value techniqueParameters ; FbxSurfaceLambert *pLambertSurface =FbxCast (pMaterial) ; - web::json::value ret =web::json::value::object () ; - MergeJsonObjects (ret, WriteMaterialParameter (U("ambient"), pLambertSurface->Ambient, pLambertSurface->AmbientFactor.Get (), values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("diffuse"), pLambertSurface->Diffuse, pLambertSurface->DiffuseFactor.Get (), values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("emission"), pLambertSurface->Emissive, pLambertSurface->EmissiveFactor.Get (), values, techniqueParameters)) ; - values [U("reflectivity")] =web::json::value::number (1.) ; - techniqueParameters [U("reflectivity")] =web::json::value::object ({{ U("type"), IOglTF::FLOAT }}) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("transparent"), pLambertSurface->TransparentColor, 1., values, techniqueParameters)) ; + Json::Value ret ; + MergeJsonObjects (ret, WriteMaterialParameter (("ambient"), pLambertSurface->Ambient, pLambertSurface->AmbientFactor.Get (), values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("diffuse"), pLambertSurface->Diffuse, pLambertSurface->DiffuseFactor.Get (), values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("emission"), pLambertSurface->Emissive, pLambertSurface->EmissiveFactor.Get (), values, techniqueParameters)) ; + values [("reflectivity")] =(1.) ; + techniqueParameters [("reflectivity")] ["type"] = IOglTF::FLOAT ; + MergeJsonObjects (ret, WriteMaterialParameter (("transparent"), pLambertSurface->TransparentColor, 1., values, techniqueParameters)) ; // gltf - opaque is 1. / transparency is 0. // pPhongSurface->TransparentColor // Transparent color property. // pPhongSurface->TransparencyFactor // Transparency factor property. This property is used to make a surface more or less opaque (0 = opaque, 1 = transparent). + auto opacity = pLambertSurface->FindProperty ("Opacity"); MergeJsonObjects (ret, WriteMaterialTransparencyParameter ( - U("transparency"), - pLambertSurface->TransparencyFactor, pLambertSurface->TransparentColor, pLambertSurface->FindProperty ("Opacity"), + ("transparency"), + pLambertSurface->TransparencyFactor, pLambertSurface->TransparentColor, opacity, values, techniqueParameters )) ; // Note: // REFLECTIVITY, INDEXOFREFRACTION are not supported by FBX. - //return (web::json::value::object ({ { U("values"), values }, { U("techniqueParameters"), techniqueParameters } })) ; - MergeJsonObjects (ret, web::json::value::object ({ { U("values"), values }, { U("techniqueParameters"), techniqueParameters } })) ; + //return (Json::Value::object ({ { ("values"), values }, { ("techniqueParameters"), techniqueParameters } })) ; + Json::Value temp; + temp["values"] = values; + temp["techniqueParameters"] = techniqueParameters; + MergeJsonObjects (ret, temp) ; return (ret) ; } -web::json::value gltfWriter::WriteConstantShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { - web::json::value values =web::json::value::object () ; - web::json::value techniqueParameters =web::json::value::object () ; +Json::Value gltfWriter::WriteConstantShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { + Json::Value values ; + Json::Value techniqueParameters ; - web::json::value ret =web::json::value::object () ; - MergeJsonObjects (ret, WriteMaterialParameter (U("emission"), pMaterial, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, values, techniqueParameters)) ; + Json::Value ret ; + MergeJsonObjects (ret, WriteMaterialParameter (("emission"), pMaterial, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, values, techniqueParameters)) ; FbxPropertyT factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sReflectionFactor, FbxDoubleDT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("reflectivity"), factorProperty, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("reflectivity"), factorProperty, values, techniqueParameters)) ; FbxPropertyT colorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sTransparentColor, FbxDouble3DT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("transparent"), colorProperty, 1., values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("transparent"), colorProperty, 1., values, techniqueParameters)) ; // gltf - opaque is 1. / transparency is 0. // pPhongSurface->TransparentColor // Transparent color property. // pPhongSurface->TransparencyFactor // Transparency factor property. This property is used to make a surface more or less opaque (0 = opaque, 1 = transparent). factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sTransparencyFactor, FbxDoubleDT, false) ; + auto opacity = pMaterial->FindProperty ("Opacity"); MergeJsonObjects (ret, WriteMaterialTransparencyParameter ( - U("transparency"), - factorProperty, colorProperty, pMaterial->FindProperty ("Opacity"), + ("transparency"), + factorProperty, colorProperty, opacity, values, techniqueParameters )) ; // Note: // REFLECTIVE, INDEXOFREFRACTION are not supported by FBX. - - MergeJsonObjects (ret, web::json::value::object ({ { U("values"), values }, { U("techniqueParameters"), techniqueParameters } })) ; + Json::Value temp; + temp["values"] = values; + temp["techniqueParameters"] = techniqueParameters; + MergeJsonObjects (ret, temp) ; return (ret) ; } -web::json::value gltfWriter::WriteBlinnShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { - web::json::value values =web::json::value::object () ; - web::json::value techniqueParameters =web::json::value::object () ; +Json::Value gltfWriter::WriteBlinnShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { + Json::Value values ; + Json::Value techniqueParameters ; - web::json::value ret =web::json::value::object () ; - MergeJsonObjects (ret, WriteMaterialParameter (U("ambient"), pMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("diffuse"), pMaterial, FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor, values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("emission"), pMaterial, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("specular"), pMaterial, FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor, values, techniqueParameters)) ; + Json::Value ret ; + MergeJsonObjects (ret, WriteMaterialParameter (("ambient"), pMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("diffuse"), pMaterial, FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("emission"), pMaterial, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("specular"), pMaterial, FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor, values, techniqueParameters)) ; FbxPropertyT factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sShininess, FbxDoubleDT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("shininess"), factorProperty, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("shininess"), factorProperty, values, techniqueParameters)) ; FbxPropertyT colorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sReflection, FbxDouble3DT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("reflective"), colorProperty, 1., values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("reflective"), colorProperty, 1., values, techniqueParameters)) ; factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sReflectionFactor, FbxDoubleDT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("reflectivity"), factorProperty, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("reflectivity"), factorProperty, values, techniqueParameters)) ; colorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sTransparentColor, FbxDouble3DT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("transparent"), colorProperty, 1., values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("transparent"), colorProperty, 1., values, techniqueParameters)) ; // gltf - opaque is 1. / transparency is 0. // pPhongSurface->TransparentColor // Transparent color property. // pPhongSurface->TransparencyFactor // Transparency factor property. This property is used to make a surface more or less opaque (0 = opaque, 1 = transparent). factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sTransparencyFactor, FbxDoubleDT, false) ; + auto opacity = pMaterial->FindProperty ("Opacity"); MergeJsonObjects (ret, WriteMaterialTransparencyParameter ( - U("transparency"), - factorProperty, colorProperty, pMaterial->FindProperty ("Opacity"), + ("transparency"), + factorProperty, colorProperty, opacity, values, techniqueParameters )) ; // Note: // INDEXOFREFRACTION is not supported by FBX. - - MergeJsonObjects (ret, web::json::value::object ({ { U("values"), values }, { U("techniqueParameters"), techniqueParameters } })) ; + Json::Value temp; + temp["values"] = values; + temp["techniqueParameters"] = techniqueParameters; + MergeJsonObjects (ret, temp) ; return (ret) ; } -web::json::value gltfWriter::WriteDefaultShadingModelWithCGFXMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { +Json::Value gltfWriter::WriteDefaultShadingModelWithCGFXMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { // Set default material to constant, in case when the reader doesn't support NVidia extension. //TODO: hlsl and CGFX support _ASSERTE( false ) ; - return (web::json::value::null ()) ; + return (Json::Value()) ; } -web::json::value gltfWriter::WriteDefaultShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { - web::json::value values =web::json::value::object () ; - web::json::value techniqueParameters =web::json::value::object () ; +Json::Value gltfWriter::WriteDefaultShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) { + Json::Value values ; + Json::Value techniqueParameters ; - web::json::value ret =web::json::value::object () ; - MergeJsonObjects (ret, WriteMaterialParameter (U("ambient"), pMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("diffuse"), pMaterial, FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor, values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("emission"), pMaterial, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, values, techniqueParameters)) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("specular"), pMaterial, FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor, values, techniqueParameters)) ; + Json::Value ret ; + MergeJsonObjects (ret, WriteMaterialParameter (("ambient"), pMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("diffuse"), pMaterial, FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("emission"), pMaterial, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("specular"), pMaterial, FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor, values, techniqueParameters)) ; //FbxProperty factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sShininess, FbxDoubleDT, false) ; FbxPropertyT factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sShininess, FbxDoubleDT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("shininess"), factorProperty, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("shininess"), factorProperty, values, techniqueParameters)) ; FbxPropertyT colorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sReflection, FbxDouble3DT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("reflective"), colorProperty, 1., values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("reflective"), colorProperty, 1., values, techniqueParameters)) ; factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sReflectionFactor, FbxDoubleDT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("reflectivity"), factorProperty, values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("reflectivity"), factorProperty, values, techniqueParameters)) ; colorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sTransparentColor, FbxDouble3DT, false) ; - MergeJsonObjects (ret, WriteMaterialParameter (U("transparent"), colorProperty, 1., values, techniqueParameters)) ; + MergeJsonObjects (ret, WriteMaterialParameter (("transparent"), colorProperty, 1., values, techniqueParameters)) ; // gltf - opaque is 1. / transparency is 0. // pPhongSurface->TransparentColor // Transparent color property. // pPhongSurface->TransparencyFactor // Transparency factor property. This property is used to make a surface more or less opaque (0 = opaque, 1 = transparent). factorProperty =pMaterial->FindProperty (FbxSurfaceMaterial::sTransparencyFactor, FbxDoubleDT, false) ; + auto opacity = pMaterial->FindProperty ("Opacity"); MergeJsonObjects (ret, WriteMaterialTransparencyParameter ( - U("transparency"), - factorProperty, colorProperty, pMaterial->FindProperty ("Opacity"), + ("transparency"), + factorProperty, colorProperty, opacity, values, techniqueParameters )) ; // Note: // INDEXOFREFRACTION is not supported by FBX. - - MergeJsonObjects (ret, web::json::value::object ({ { U("values"), values }, { U("techniqueParameters"), techniqueParameters } })) ; + Json::Value temp; + temp["values"] = values; + temp["techniqueParameters"] = techniqueParameters; + MergeJsonObjects (ret, temp) ; return (ret) ; } #define AssignDefaultColor(pszName, defaultColor) \ { \ - values [pszName] =web::json::value::array ({ { defaultColor [0], defaultColor [1], defaultColor [2], 1. } }) ; \ - techniqueParameters [pszName] =web::json::value::object ({{ U("type"), IOglTF::FLOAT_VEC4 }}) ; \ + auto &colorValues = values [pszName]; \ + colorValues[0] = defaultColor [0]; \ + colorValues[1] = defaultColor [1]; \ + colorValues[2] = defaultColor [2]; \ + colorValues[3] = 1. ; \ + techniqueParameters [pszName] [("type")] = IOglTF::FLOAT_VEC4 ; \ } -web::json::value gltfWriter::WriteDefaultShadingModelMaterial (FbxNode *pNode) { - web::json::value values =web::json::value::object () ; - web::json::value techniqueParameters =web::json::value::object () ; +Json::Value gltfWriter::WriteDefaultShadingModelMaterial (FbxNode *pNode) { + Json::Value values ; + Json::Value techniqueParameters ; - web::json::value ret =web::json::value::object () ; + Json::Value ret ; //FbxScene *pScene =pNode->GetScene () ; //FbxColor ambient (pScene->GetGlobalSettings ().GetAmbientColor ()) ; - //AssignDefaultColor (U("ambient"), ambient) ; + //AssignDefaultColor (("ambient"), ambient) ; FbxProperty property =pNode->GetNodeAttribute ()->Color ; FbxDouble3 color =property.IsValid () ? property.Get () : FbxNodeAttribute::sDefaultColor ; - AssignDefaultColor (U("diffuse"), color) ; - - MergeJsonObjects (ret, web::json::value::object ({ { U("values"), values }, { U("techniqueParameters"), techniqueParameters } })) ; + AssignDefaultColor (("diffuse"), color) ; + Json::Value temp; + temp["values"] = values; + temp["techniqueParameters"] = techniqueParameters; + MergeJsonObjects (ret, temp) ; return (ret) ; } diff --git a/IO-glTF/gltfWriter-Mesh.cpp b/IO-glTF/gltfWriter-Mesh.cpp index ca7231a..c9ed720 100644 --- a/IO-glTF/gltfWriter-Mesh.cpp +++ b/IO-glTF/gltfWriter-Mesh.cpp @@ -26,29 +26,36 @@ namespace _IOglTF_NS_ { //----------------------------------------------------------------------------- -web::json::value gltfWriter::WriteMesh (FbxNode *pNode) { - web::json::value meshDef =web::json::value::object () ; - meshDef [U("name")] =web::json::value::string (nodeId (pNode, true)) ; +Json::Value gltfWriter::WriteMesh (FbxNode *pNode) { + Json::Value meshDef ; + meshDef [("name")] =(nodeId (pNode, true)) ; - //if ( _json [U("meshes")].has_field (meshDef [U("name")].as_string ()) ) { + //if ( _json [("meshes")].isMember (meshDef [("name")].asString ()) ) { if ( isKnownId (pNode->GetNodeAttribute ()->GetUniqueID ()) ) { // The mesh/material/... were already exported, create only the transform node - web::json::value node =WriteNode (pNode) ; - web::json::value ret =web::json::value::object ({ { U("nodes"), node } }) ; + Json::Value node =WriteNode (pNode) ; + Json::Value ret ; + ret[("nodes")] = node ; return (ret) ; } - web::json::value meshPrimitives =web::json::value::array () ; - web::json::value accessorsAndBufferViews =web::json::value::object ({ - { U("accessors"), web::json::value::object () }, - { U("bufferViews"), web::json::value::object () } - }) ; - web::json::value materials =web::json::value::object ({ { U("materials"), web::json::value::object () } }) ; - web::json::value techniques =web::json::value::object ({ { U("techniques"), web::json::value::object () } }) ; - web::json::value programs =web::json::value::object ({ { U("programs"), web::json::value::object () } }) ; - web::json::value images =web::json::value::object ({ { U("images"), web::json::value::object () } }) ; - web::json::value samplers =web::json::value::object ({ { U("samplers"), web::json::value::object () } }) ; - web::json::value textures =web::json::value::object ({ { U("textures"), web::json::value::object () } }) ; + Json::Value meshPrimitives ; + Json::Value accessorsAndBufferViews ; + accessorsAndBufferViews[("accessors")] = Json::Value( Json::objectValue ); + accessorsAndBufferViews[("bufferViews")] = Json::Value( Json::objectValue ); + + Json::Value materials ; + materials["materials"] = Json::Value( Json::objectValue ) ; + Json::Value techniques ; + techniques[("techniques")] = Json::Value( Json::objectValue ) ; + Json::Value programs ; + programs[("programs")] = Json::Value( Json::objectValue ) ; + Json::Value images ; + images[("images")] = Json::Value( Json::objectValue ) ; + Json::Value samplers ; + samplers[("samplers")] = Json::Value( Json::objectValue ) ; + Json::Value textures ; + textures[("textures")] = Json::Value( Json::objectValue ) ; FbxMesh *pMesh =pNode->GetMesh () ; //FbxCast(pNode->GetNodeAttribute ()) ; pMesh->ComputeBBox () ; @@ -68,17 +75,16 @@ web::json::value gltfWriter::WriteMesh (FbxNode *pNode) { // - Warnings for unsupported layer element types: polygon groups, undefined int nbLayers =pMesh->GetLayerCount () ; - web::json::value primitive=web::json::value::object ({ - { U("attributes"), web::json::value::object () }, - { U("mode"), IOglTF::TRIANGLES } // Allowed values are 0 (POINTS), 1 (LINES), 2 (LINE_LOOP), 3 (LINE_STRIP), 4 (TRIANGLES), 5 (TRIANGLE_STRIP), and 6 (TRIANGLE_FAN). - }) ; - -////web::json::value elts =web::json::value::object ({ -//// { U("normals"), web::json::value::object () }, -//// { U("uvs"), web::json::value::object () }, -//// { U("colors"), web::json::value::object () } + Json::Value primitive ; + primitive[("attributes")] = Json::Value( Json::objectValue ) ; + primitive[("mode")] = IOglTF::TRIANGLES ; // Allowed values are 0 (POINTS), 1 (LINES), 2 (LINE_LOOP), 3 (LINE_STRIP), 4 (TRIANGLES), 5 (TRIANGLE_STRIP), and 6 (TRIANGLE_FAN). + +////Json::Value elts =Json::Value::object ({ +//// { ("normals"), Json::Value::object () }, +//// { ("uvs"), Json::Value::object () }, +//// { ("colors"), Json::Value::object () } ////}) ; - web::json::value localAccessorsAndBufferViews =web::json::value::object () ; + Json::Value localAccessorsAndBufferViews ; gltfwriterVBO vbo (pMesh) ; vbo.GetLayerElements (true) ; @@ -94,24 +100,24 @@ web::json::value gltfWriter::WriteMesh (FbxNode *pNode) { _uvSets =vbo.getUvSets () ; - web::json::value vertex =WriteArrayWithMinMax (out_positions, pMesh->GetNode (), U("_Positions")) ; + Json::Value vertex =WriteArrayWithMinMax (out_positions, pMesh->GetNode (), ("_Positions")) ; MergeJsonObjects (localAccessorsAndBufferViews, vertex); - primitive [U("attributes")] [U("POSITION")] =web::json::value::string (GetJsonFirstKey (vertex [U("accessors")])) ; + primitive [("attributes")] [("POSITION")] =(GetJsonFirstKey (vertex [("accessors")])) ; if ( out_normals.size () ) { - utility::string_t st (U("_Normals")) ; - web::json::value ret =WriteArrayWithMinMax (out_normals, pMesh->GetNode (), st.c_str ()) ; + std::string st (("_Normals")) ; + Json::Value ret =WriteArrayWithMinMax (out_normals, pMesh->GetNode (), st.c_str ()) ; MergeJsonObjects (localAccessorsAndBufferViews, ret) ; - st=U("NORMAL") ; - primitive [U("attributes")] [st] =web::json::value::string (GetJsonFirstKey (ret [U("accessors")])) ; + st=("NORMAL") ; + primitive [("attributes")] [st] =(GetJsonFirstKey (ret [("accessors")])) ; } if ( out_uvs.size () ) { // todo more than 1 - std::map::iterator iter =_uvSets.begin () ; - utility::string_t st (U("_") + iter->second) ; - web::json::value ret =WriteArrayWithMinMax (out_uvs, pMesh->GetNode (), st.c_str ()) ; + std::map::iterator iter =_uvSets.begin () ; + std::string st (("_") + iter->second) ; + Json::Value ret =WriteArrayWithMinMax (out_uvs, pMesh->GetNode (), st.c_str ()) ; MergeJsonObjects (localAccessorsAndBufferViews, ret) ; - primitive [U("attributes")] [iter->second] =web::json::value::string (GetJsonFirstKey (ret [U("accessors")])) ; + primitive [("attributes")] [iter->second] =(GetJsonFirstKey (ret [("accessors")])) ; } int nb=(int)out_vcolors.size () ; @@ -119,16 +125,16 @@ web::json::value gltfWriter::WriteMesh (FbxNode *pNode) { std::vector vertexColors_ (nb); for ( int i =0 ; i < nb ; i++ ) vertexColors_.push_back (FbxDouble4 (out_vcolors [i].mRed, out_vcolors [i].mGreen, out_vcolors [i].mBlue, out_vcolors [i].mAlpha)) ; - utility::string_t st (U("_Colors0")) ; - web::json::value ret =WriteArrayWithMinMax (vertexColors_, pMesh->GetNode (), st.c_str ()) ; + std::string st (("_Colors0")) ; + Json::Value ret =WriteArrayWithMinMax (vertexColors_, pMesh->GetNode (), st.c_str ()) ; MergeJsonObjects (localAccessorsAndBufferViews, ret) ; - st =U("COLOR_0") ; - primitive [U("attributes")] [st] =web::json::value::string (GetJsonFirstKey (ret [U("accessors")])) ; + st =("COLOR_0") ; + primitive [("attributes")] [st] =(GetJsonFirstKey (ret [("accessors")])) ; } // Get mesh face indices - web::json::value polygons =WriteArray (out_indices, 1, pMesh->GetNode (), U("_Polygons")) ; - primitive [U("indices")] =web::json::value::string (GetJsonFirstKey (polygons [U("accessors")])) ; + Json::Value polygons =WriteArray (out_indices, 1, pMesh->GetNode (), ("_Polygons")) ; + primitive [("indices")] =(GetJsonFirstKey (polygons [("accessors")])) ; MergeJsonObjects (accessorsAndBufferViews, polygons) ; MergeJsonObjects (accessorsAndBufferViews, localAccessorsAndBufferViews) ; @@ -136,30 +142,30 @@ web::json::value gltfWriter::WriteMesh (FbxNode *pNode) { // Get material FbxLayer *pLayer =gltfwriterVBO::getLayer (pMesh, FbxLayerElement::eMaterial) ; if ( pLayer == nullptr ) { - //ucout << U("Info: (") << utility::conversions::to_string_t (pNode->GetTypeName ()) - // << U(") ") << utility::conversions::to_string_t (pNode->GetName ()) - // << U(" no material on Layer: ") + //std::cout << ("Info: (") << utility::conversions::to_string_t (pNode->GetTypeName ()) + // << (") ") << utility::conversions::to_string_t (pNode->GetName ()) + // << (" no material on Layer: ") // << iLayer // << std::endl ; // Create default material - web::json::value ret =WriteDefaultMaterial (pNode) ; - if ( ret.is_string () ) { - primitive [U("material")] =ret ; + Json::Value ret =WriteDefaultMaterial (pNode) ; + if ( ret.isString () ) { + primitive [("material")] =ret ; } else { - primitive [U("material")] =web::json::value::string (GetJsonFirstKey (ret [U("materials")])) ; + primitive [("material")] =(GetJsonFirstKey (ret [("materials")])) ; - MergeJsonObjects (materials [U("materials")], ret [U("materials")]) ; + MergeJsonObjects (materials [("materials")], ret [("materials")]) ; - utility::string_t techniqueName =GetJsonFirstKey (ret [U("techniques")]) ; - web::json::value techniqueParameters =ret [U("techniques")] [techniqueName] [U("parameters")] ; + std::string techniqueName =GetJsonFirstKey (ret [("techniques")]) ; + Json::Value techniqueParameters =ret [("techniques")] [techniqueName] [("parameters")] ; AdditionalTechniqueParameters (pNode, techniqueParameters, out_normals.size () != 0) ; - TechniqueParameters (pNode, techniqueParameters, primitive [U("attributes")], localAccessorsAndBufferViews [U("accessors")], false) ; + TechniqueParameters (pNode, techniqueParameters, primitive [("attributes")], localAccessorsAndBufferViews [("accessors")], false) ; ret =WriteTechnique (pNode, nullptr, techniqueParameters) ; //MergeJsonObjects (techniques, ret) ; - techniques [U("techniques")] [techniqueName] =ret ; + techniques [("techniques")] [techniqueName] =ret ; - utility::string_t programName =ret [U("program")].as_string () ; - web::json::value attributes =ret [U("attributes")] ; + std::string programName =ret [("program")].asString () ; + Json::Value attributes =ret [("attributes")] ; ret =WriteProgram (pNode, nullptr, programName, attributes) ; MergeJsonObjects (programs, ret) ; } @@ -168,53 +174,56 @@ web::json::value gltfWriter::WriteMesh (FbxNode *pNode) { int materialCount =pLayerElementMaterial ? pNode->GetMaterialCount () : 0 ; if ( materialCount > 1 ) { _ASSERTE( materialCount > 1 ) ; - ucout << U("Warning: (") << utility::conversions::to_string_t (pNode->GetTypeName ()) - << U(") ") << utility::conversions::to_string_t (pNode->GetName ()) - << U(" got more than one material. glTF supports one material per primitive (FBX Layer).") + std::cout << ("Warning: (") << (pNode->GetTypeName ()) + << (") ") << (pNode->GetName ()) + << (" got more than one material. glTF supports one material per primitive (FBX Layer).") << std::endl ; } // TODO: need to be revisited when glTF will support more than one material per layer/primitive materialCount =materialCount == 0 ? 0 : 1 ; for ( int i =0 ; i < materialCount ; i++ ) { - web::json::value ret =WriteMaterial (pNode, pNode->GetMaterial (i)) ; - if ( ret.is_string () ) { - primitive [U("material")] =ret ; + Json::Value ret =WriteMaterial (pNode, pNode->GetMaterial (i)) ; + if ( ret.isString () ) { + primitive [("material")] =ret ; continue ; } - primitive [U("material")]=web::json::value::string (GetJsonFirstKey (ret [U("materials")])) ; - - MergeJsonObjects (materials [U("materials")], ret [U("materials")]) ; - if ( ret.has_field (U("images")) ) - MergeJsonObjects (images [U("images")], ret [U("images")]) ; - if ( ret.has_field (U("samplers")) ) - MergeJsonObjects (samplers [U("samplers")], ret [U("samplers")]) ; - if ( ret.has_field (U("textures")) ) - MergeJsonObjects (textures [U("textures")], ret [U("textures")]) ; - - utility::string_t techniqueName =GetJsonFirstKey (ret [U("techniques")]) ; - web::json::value techniqueParameters =ret [U("techniques")] [techniqueName] [U("parameters")] ; + primitive [("material")]=(GetJsonFirstKey (ret [("materials")])) ; + + MergeJsonObjects (materials [("materials")], ret [("materials")]) ; + if ( ret.isMember (("images")) ) + MergeJsonObjects (images [("images")], ret [("images")]) ; + if ( ret.isMember (("samplers")) ) + MergeJsonObjects (samplers [("samplers")], ret [("samplers")]) ; + if ( ret.isMember (("textures")) ) + MergeJsonObjects (textures [("textures")], ret [("textures")]) ; + + std::string techniqueName =GetJsonFirstKey (ret [("techniques")]) ; + Json::Value techniqueParameters =ret [("techniques")] [techniqueName] [("parameters")] ; AdditionalTechniqueParameters (pNode, techniqueParameters, out_normals.size () != 0) ; - TechniqueParameters (pNode, techniqueParameters, primitive [U("attributes")], localAccessorsAndBufferViews [U("accessors")]) ; + TechniqueParameters (pNode, techniqueParameters, primitive [("attributes")], localAccessorsAndBufferViews [("accessors")]) ; ret =WriteTechnique (pNode, pNode->GetMaterial (i), techniqueParameters) ; //MergeJsonObjects (techniques, ret) ; - techniques [U("techniques")] [techniqueName] =ret ; + techniques [("techniques")] [techniqueName] =ret ; - utility::string_t programName =ret [U("program")].as_string () ; - web::json::value attributes =ret [U("attributes")] ; + std::string programName =ret [("program")].asString () ; + Json::Value attributes =ret [("attributes")] ; ret =WriteProgram (pNode, pNode->GetMaterial (i), programName, attributes) ; MergeJsonObjects (programs, ret) ; } } meshPrimitives [meshPrimitives.size ()] =primitive ; - meshDef [U("primitives")] =meshPrimitives ; + meshDef [("primitives")] =meshPrimitives ; - web::json::value lib =web::json::value::object ({ { nodeId (pNode, true, true), meshDef } }) ; + Json::Value lib ; + lib[nodeId (pNode, true, true)] = meshDef ; - web::json::value node =WriteNode (pNode) ; + Json::Value node =WriteNode (pNode) ; //if ( pMesh->GetShapeCount () ) // WriteControllerShape (pMesh) ; // Create a controller - web::json::value ret =web::json::value::object ({ { U("meshes"), lib }, { U("nodes"), node } }) ; + Json::Value ret ; + ret[("meshes")] = lib ; + ret[("nodes")] = node ; MergeJsonObjects (ret, accessorsAndBufferViews) ; MergeJsonObjects (ret, images) ; MergeJsonObjects (ret, materials) ; diff --git a/IO-glTF/gltfWriter-Null.cpp b/IO-glTF/gltfWriter-Null.cpp index e9742c2..2e13322 100644 --- a/IO-glTF/gltfWriter-Null.cpp +++ b/IO-glTF/gltfWriter-Null.cpp @@ -24,9 +24,10 @@ namespace _IOglTF_NS_ { //----------------------------------------------------------------------------- -web::json::value gltfWriter::WriteNull (FbxNode *pNode) { - web::json::value node =WriteNode (pNode) ; - web::json::value ret =web::json::value::object ({ { U("nodes"), node } }) ; +Json::Value gltfWriter::WriteNull (FbxNode *pNode) { + Json::Value node =WriteNode (pNode) ; + Json::Value ret ; + ret["nodes"] =node ; return (ret) ; } diff --git a/IO-glTF/gltfWriter-Program.cpp b/IO-glTF/gltfWriter-Program.cpp index 4cc2119..1d14a1c 100644 --- a/IO-glTF/gltfWriter-Program.cpp +++ b/IO-glTF/gltfWriter-Program.cpp @@ -23,10 +23,11 @@ namespace _IOglTF_NS_ { -web::json::value gltfWriter::WriteProgram (FbxNode *pNode, FbxSurfaceMaterial *pMaterial, utility::string_t programName, web::json::value &attributes) { - web::json::value programAttributes =web::json::value::array () ; - for ( const auto &iter : attributes.as_object () ) - programAttributes [programAttributes.size ()] =web::json::value::string (iter.first) ; +Json::Value gltfWriter::WriteProgram (FbxNode *pNode, FbxSurfaceMaterial *pMaterial, std::string programName, Json::Value &attributes) { + Json::Value programAttributes ; + auto memberNames = attributes.getMemberNames(); + for ( const auto &name : memberNames ) + programAttributes [programAttributes.size ()] =(name) ; // Get the implementation to see if it's a hardware shader. if ( pMaterial != nullptr ) { @@ -48,36 +49,35 @@ web::json::value gltfWriter::WriteProgram (FbxNode *pNode, FbxSurfaceMaterial *p // //pImplementation =pNode->GetImplementation (0) ; //} } - FbxString filename =FbxPathUtils::GetFileName (utility::conversions::to_utf8string (_fileName).c_str (), false) ; + FbxString filename =FbxPathUtils::GetFileName ((_fileName).c_str (), false) ; - web::json::value program =web::json::value::object ({ - { U("attributes"), programAttributes }, - { U("name"), web::json::value::string (programName) }, - //{ U("fragmentShader"), web::json::value::string (utility::conversions::to_string_t (filename.Buffer ()) + U("0FS")) }, - //{ U("vertexShader"), web::json::value::string (utility::conversions::to_string_t (filename.Buffer ()) + U("0VS")) } - { U("fragmentShader"), web::json::value::string (programName + U("FS")) }, - { U("vertexShader"), web::json::value::string (programName + U("VS")) } - }) ; - web::json::value lib =web::json::value::object ({{ programName, program }}) ; + Json::Value program ; + program[("attributes")] = programAttributes ; + program[("name")] = (programName) ; + program[("fragmentShader")] = (programName + ("FS")) ; + program[("vertexShader")] = (programName + ("VS")) ; - web::json::value shaders =WriteShaders (pNode, program) ; + Json::Value lib ; + lib[programName] = program ; - return (web::json::value::object ({ { U("programs"), lib }, { U("shaders"), shaders } })) ; + Json::Value shaders =WriteShaders (pNode, program) ; + Json::Value ret; + ret["programs"] = lib; + ret["shaders"] = shaders; + return ret ; } -web::json::value gltfWriter::WriteShaders (FbxNode *pNode, web::json::value &program) { - web::json::value fragmentShader =web::json::value::object ({ - { U("type"), web::json::value::number ((int)IOglTF::FRAGMENT_SHADER) }, - { U("uri"), web::json::value::string (program [U("fragmentShader")].as_string () + U(".glsl")) } - }) ; - web::json::value vertexShader =web::json::value::object ({ - { U ("type"), web::json::value::number ((int)IOglTF::VERTEX_SHADER) }, - { U ("uri"), web::json::value::string (program [U("vertexShader")].as_string () + U(".glsl")) } - }) ; - return (web::json::value::object ({ - { program [U("fragmentShader")].as_string (), fragmentShader }, - { program [U ("vertexShader")].as_string (), vertexShader } - })) ; +Json::Value gltfWriter::WriteShaders (FbxNode *pNode, Json::Value &program) { + Json::Value ret ; + auto &fragment = ret[program [("fragmentShader")].asString ()]; + fragment[("type")] = ((int)IOglTF::FRAGMENT_SHADER) ; + fragment[("uri")] = (program [("fragmentShader")].asString () + (".glsl")) ; + + auto &vertex = ret[program [("vertexShader")].asString ()]; + vertex[("type")] = ((int)IOglTF::VERTEX_SHADER) ; + vertex[("uri")] = (program [("vertexShader")].asString () + (".glsl")) ; + + return ret; } } diff --git a/IO-glTF/gltfWriter-Scene.cpp b/IO-glTF/gltfWriter-Scene.cpp index 87aea9e..b313c18 100644 --- a/IO-glTF/gltfWriter-Scene.cpp +++ b/IO-glTF/gltfWriter-Scene.cpp @@ -26,9 +26,10 @@ namespace _IOglTF_NS_ { bool gltfWriter::WriteScene (FbxScene *pScene, int poseIndex /*=-1*/) { FbxNode *pRoot =pScene->GetRootNode () ; FbxPose *pPose =poseIndex >= 0 ? pScene->GetPose (poseIndex) : nullptr ; - utility::string_t szName =utility::conversions::to_string_t (pScene->GetName ()) ; - _json [U("scene")] =web::json::value::string (szName) ; - _json [U("scenes")] =web::json::value::object ({ { szName, web::json::value::object ({ { U("nodes"), web::json::value::array () } }) } }) ; + std::string szName = (pScene->GetName ()) ; + _json [("scene")] =(szName) ; + auto &scenes = _json [("scenes")]; + scenes[szName]["nodes"] = Json::Value( Json::arrayValue ) ; //FbxDouble3 translation =pRoot->LclTranslation.Get () ; //FbxDouble3 rotation =pRoot->LclRotation.Get () ; diff --git a/IO-glTF/gltfWriter-Shaders.cpp b/IO-glTF/gltfWriter-Shaders.cpp index b47fc61..2ad8266 100644 --- a/IO-glTF/gltfWriter-Shaders.cpp +++ b/IO-glTF/gltfWriter-Shaders.cpp @@ -25,74 +25,74 @@ namespace _IOglTF_NS_ { bool gltfWriter::WriteShaders () { - //web::json::value buffer =web::json::value::object () ; + //Json::Value buffer ; //FbxString filename =FbxPathUtils::GetFileName (utility::conversions::to_utf8string (_fileName).c_str (), false) ; - //buffer [U("name")] =web::json::value::string (utility::conversions::to_string_t (filename.Buffer ())) ; + //buffer [("name")] =(utility::conversions::to_string_t (filename.Buffer ())) ; - //buffer [U("uri")] =web::json::value::string (utility::conversions::to_string_t ((filename + ".bin").Buffer ())) ; + //buffer [("uri")] =(utility::conversions::to_string_t ((filename + ".bin").Buffer ())) ; //// The Buffer file should be fully completed by now. //if ( GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_EMBEDMEDIA, false) ) { // // data:[][;charset=][;base64], - // buffer [U("uri")] =web::json::value::string (IOglTF::dataURI (_bin)) ; + // buffer [("uri")] =(IOglTF::dataURI (_bin)) ; //} //if ( _writeDefaults ) - // buffer [U("type")] =web::json::value::string (U("arraybuffer")) ; ; // default is arraybuffer - //buffer [U("byteLength")] =web::json::value::number ((int)_bin.tellg ()) ; + // buffer [("type")] =(("arraybuffer")) ; ; // default is arraybuffer + //buffer [("byteLength")] =((int)_bin.tellg ()) ; - //_json [U("buffers")] [utility::conversions::to_string_t (filename.Buffer ())] =buffer ; + //_json [("buffers")] [utility::conversions::to_string_t (filename.Buffer ())] =buffer ; - //web::json::value techs =_json [U("techniques")] ; + //Json::Value techs =_json [("techniques")] ; //for ( auto iter =techs.as_object ().begin () ; iter != techs.as_object ().end () ; iter++ ) { // glslTech test (iter->second) ; - // ucout << test.vertexShader ().source () + // std::cout << test.vertexShader ().source () // << std::endl ; //} - web::json::value materials =_json [U("materials")] ; - for ( auto iter =materials.as_object ().begin () ; iter != materials.as_object ().end () ; iter++ ) { - utility::string_t name =iter->first ; - utility::string_t techniqueName =iter->second [U("technique")].as_string () ; + Json::Value materials =_json [("materials")] ; + auto memberNames = materials.getMemberNames(); + for ( auto &name : memberNames ) { + std::string techniqueName = materials[name] [("technique")].asString () ; glslTech tech ( - _json [U("techniques")] [techniqueName], - iter->second [U("values")], + _json [("techniques")] [techniqueName], + materials[name] [("values")], _json ) ; - utility::string_t programName =_json [U("techniques")] [techniqueName] [U("program")].as_string () ; - utility::string_t vsName =_json [U("programs")] [programName] [U("vertexShader")].as_string () ; - utility::string_t fsName =_json [U("programs")] [programName] [U("fragmentShader")].as_string () ; + std::string programName =_json [("techniques")] [techniqueName] [("program")].asString () ; + std::string vsName =_json [("programs")] [programName] [("vertexShader")].asString () ; + std::string fsName =_json [("programs")] [programName] [("fragmentShader")].asString () ; if ( GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_EMBEDMEDIA, false) ) { // data:[][;charset=][;base64], - _json [U("shaders")] [vsName] [U("uri")] =web::json::value::string (IOglTF::dataURI (tech.vertexShader ().source ())) ; - _json [U("shaders")] [fsName] [U("uri")] =web::json::value::string (IOglTF::dataURI (tech.fragmentShader ().source ())) ; + _json [("shaders")] [vsName] [("uri")] =(IOglTF::dataURI (tech.vertexShader ().source ())) ; + _json [("shaders")] [fsName] [("uri")] =(IOglTF::dataURI (tech.fragmentShader ().source ())) ; } else { - FbxString gltfFilename (utility::conversions::to_utf8string (_fileName).c_str ()) ; - utility::string_t vsFilename =_json [U("shaders")] [vsName] [U("uri")].as_string () ; + FbxString gltfFilename ((_fileName).c_str ()) ; + std::string vsFilename =_json [("shaders")] [vsName] [("uri")].asString () ; { - FbxString shaderFilename (utility::conversions::to_utf8string (vsFilename).c_str ()) ; + FbxString shaderFilename ((vsFilename).c_str ()) ; #if defined(_WIN32) || defined(_WIN64) shaderFilename =FbxPathUtils::GetFolderName (gltfFilename) + "\\" + shaderFilename ; #else - shaderFilename =FbxPathUtils::GetFolderName (fileName) + "/" + shaderFilename ; + shaderFilename =FbxPathUtils::GetFolderName (vsFilename.c_str()) + "/" + shaderFilename ; #endif - std::wfstream shaderFile (shaderFilename, std::ios::out | std::ofstream::binary) ; + std::fstream shaderFile (shaderFilename, std::ios::out | std::ofstream::binary) ; //_bin.seekg (0, std::ios_base::beg) ; shaderFile.write (tech.vertexShader ().source ().c_str (), tech.vertexShader ().source ().length ()) ; shaderFile.close () ; } - utility::string_t fsFileame =_json [U("shaders")] [fsName] [U("uri")].as_string () ; + std::string fsFilename =_json [("shaders")] [fsName] [("uri")].asString () ; { - FbxString shaderFilename (utility::conversions::to_utf8string (fsFileame).c_str ()) ; + FbxString shaderFilename ((fsFilename).c_str ()) ; #if defined(_WIN32) || defined(_WIN64) shaderFilename =FbxPathUtils::GetFolderName (gltfFilename) + "\\" + shaderFilename ; #else - shaderFilename =FbxPathUtils::GetFolderName (fileName) + "/" + shaderFilename ; + shaderFilename =FbxPathUtils::GetFolderName (fsFilename.c_str()) + "/" + shaderFilename ; #endif - std::wfstream shaderFile (shaderFilename, std::ios::out | std::ofstream::binary) ; + std::fstream shaderFile (shaderFilename, std::ios::out | std::ofstream::binary) ; //_bin.seekg (0, std::ios_base::beg) ; shaderFile.write (tech.fragmentShader ().source ().c_str (), tech.fragmentShader ().source ().length ()) ; shaderFile.close () ; diff --git a/IO-glTF/gltfWriter-Technique.cpp b/IO-glTF/gltfWriter-Technique.cpp index 3ec8d3c..5ab2809 100644 --- a/IO-glTF/gltfWriter-Technique.cpp +++ b/IO-glTF/gltfWriter-Technique.cpp @@ -23,21 +23,20 @@ namespace _IOglTF_NS_ { -void gltfWriter::AdditionalTechniqueParameters (FbxNode *pNode, web::json::value &techniqueParameters, bool bHasNormals /*=false*/) { +void gltfWriter::AdditionalTechniqueParameters (FbxNode *pNode, Json::Value &techniqueParameters, bool bHasNormals /*=false*/) { if ( bHasNormals ) { - techniqueParameters [U("normalMatrix")] =web::json::value::object ({ // normal matrix - { U("semantic"), web::json::value::string (U("MODELVIEWINVERSETRANSPOSE")) }, - { U("type"), web::json::value::number ((int)IOglTF::FLOAT_MAT3) } - }) ; + auto &normalMat = techniqueParameters [("normalMatrix")]; + normalMat[("semantic")] = (("MODELVIEWINVERSETRANSPOSE")); + normalMat[("type")] =((int)IOglTF::FLOAT_MAT3); } - techniqueParameters [U("modelViewMatrix")] =web::json::value::object ({ // modeliew matrix - { U("semantic"), web::json::value::string (U("MODELVIEW")) }, - { U("type"), web::json::value::number ((int)IOglTF::FLOAT_MAT4) } - }) ; - techniqueParameters [U("projectionMatrix")] =web::json::value::object ({ // projection matrix - { U("semantic"), web::json::value::string (U("PROJECTION")) }, - { U("type"), web::json::value::number ((int)IOglTF::FLOAT_MAT4) } - }) ; + auto &modelMat = techniqueParameters [("modelViewMatrix")]; + modelMat[("semantic")] = (("MODELVIEW")); + modelMat[("type")] = ((int)IOglTF::FLOAT_MAT4); + + auto &projMat = techniqueParameters [("projectionMatrix")]; + projMat[("semantic")] = (("PROJECTION")); + projMat[("type")] = ((int)IOglTF::FLOAT_MAT4); + //d:\projects\gltf\converter\collada2gltf\shaders\commonprofileshaders.cpp #905 //if ( hasSkinning ) { @@ -57,156 +56,162 @@ void gltfWriter::AdditionalTechniqueParameters (FbxNode *pNode, web::json::value FbxLight *pLight =pNode->GetScene ()->RootProperty.GetSrcObject (i) ; if ( lightCount == 1 && pLight->LightType.Get () == FbxLight::EType::ePoint ) return ; - //utility::string_t name =nodeId (pLight->GetNode ()) ; - utility::string_t name =utility::conversions::to_string_t (pLight->GetTypeName ()) ; + //std::string name =nodeId (pLight->GetNode ()) ; + std::string name =(pLight->GetTypeName ()) ; std::transform (name.begin (), name.end (), name.begin (), ::tolower) ; if ( pLight->LightType.Get () == FbxLight::EType::ePoint ) { - techniqueParameters [name + utility::conversions::to_string_t (i) + U("Color")] =web::json::value::object ({ // Color - { U("type"), web::json::value::number ((int)IOglTF::FLOAT_VEC3) }, - { U("value"), web::json::value::array ({{ pLight->Color.Get () [0], pLight->Color.Get () [1], pLight->Color.Get () [2] }}) } - }) ; + auto &colorVals =techniqueParameters [name + std::to_string (i) + ("Color")]; + colorVals[("type")] = ((int)IOglTF::FLOAT_VEC3); + auto &colorValsArr = colorVals[("value")]; + colorValsArr[0] = pLight->Color.Get () [0]; + colorValsArr[1] = pLight->Color.Get () [1]; + colorValsArr[2] = pLight->Color.Get () [2]; } else { - utility::string_t light_id =utility::conversions::to_string_t (nodeId (pLight->GetNode (), false)) ; - techniqueParameters [name + utility::conversions::to_string_t (i) + U("Color")] =web::json::value::object ({ // Color - { U("type"), web::json::value::number ((int)IOglTF::FLOAT_VEC3) }, - { U("value"), web::json::value::array ({{ pLight->Color.Get () [0], pLight->Color.Get () [1], pLight->Color.Get () [2] }}) } - }) ; - techniqueParameters [name + utility::conversions::to_string_t (i) + U("Transform")] =web::json::value::object ({ // Transform - { U("semantic"), web::json::value::string (U("MODELVIEW")) }, - { U("node"), web::json::value::string (light_id) }, - { U("type"), web::json::value::number ((int)IOglTF::FLOAT_MAT4) } - }) ; + std::string light_id =(nodeId (pLight->GetNode (), false)) ; + auto &colorVal = techniqueParameters [name + std::to_string (i) + ("Color")]; + colorVal[("type")] = ((int)IOglTF::FLOAT_VEC3); + auto &colorValArr = colorVal["values"]; + colorValArr[0] = pLight->Color.Get () [0]; + colorValArr[1] = pLight->Color.Get () [1]; + colorValArr[2] = pLight->Color.Get () [2]; + + auto &transVal = techniqueParameters [name + std::to_string(i) + ("Transform")]; + transVal[("semantic")] = ("MODELVIEW"); + transVal[("node")] = (light_id); + transVal[("type")] = ((int)IOglTF::FLOAT_MAT4); + if ( pLight->LightType.Get () == FbxLight::EType::eDirectional ) { - web::json::value lightDef =web::json::value::object () ; + Json::Value lightDef ; lightAttenuation (pLight, lightDef) ; - if ( !lightDef [U("constantAttenuation")].is_null () ) - techniqueParameters [name + utility::conversions::to_string_t (i) + U("ConstantAttenuation")] =web::json::value::object ({ - { U("type"), web::json::value::number ((int)IOglTF::FLOAT) }, - { U("value"), lightDef [U("constantAttenuation")] } - }) ; - if ( !lightDef [U("linearAttenuation")].is_null () ) - techniqueParameters [name + utility::conversions::to_string_t (i) + U("LinearAttenuation")] =web::json::value::object ({ - { U("type"), web::json::value::number ((int)IOglTF::FLOAT) }, - { U("value"), lightDef [U("linearAttenuation")] } - }) ; - if ( !lightDef [U("quadraticAttenuation")].is_null () ) - techniqueParameters [name + utility::conversions::to_string_t (i) + U("QuadraticAttenuation")] =web::json::value::object ({ - { U("type"), web::json::value::number ((int)IOglTF::FLOAT) }, - { U("value"), lightDef [U("quadraticAttenuation")] } - }) ; + if ( !lightDef [("constantAttenuation")].isNull () ) { + auto &attenVal = techniqueParameters [name + std::to_string(i) + ("ConstantAttenuation")]; + attenVal[("type")] = ((int)IOglTF::FLOAT); + attenVal[("value")] = lightDef [("constantAttenuation")]; + } + if ( !lightDef [("linearAttenuation")].isNull () ) { + auto &attenVal = techniqueParameters [name + std::to_string(i) + ("LinearAttenuation")] ; + attenVal[("type")] = ((int)IOglTF::FLOAT) ; + attenVal[("value")] = lightDef [("linearAttenuation")]; + } + if ( !lightDef [("quadraticAttenuation")].isNull () ) { + auto &attenVal = techniqueParameters [name + std::to_string (i) + ("QuadraticAttenuation")]; + attenVal[("type")] = ((int)IOglTF::FLOAT); + attenVal[("value")] = lightDef [("quadraticAttenuation")]; + } } if ( pLight->LightType.Get () == FbxLight::EType::eSpot ) { - techniqueParameters [name + utility::conversions::to_string_t (i) + U("InverseTransform")] =web::json::value::object ({ - { U("semantic"), web::json::value::string (U("MODELVIEWINVERSE")) }, - { U("node"), web::json::value::string (utility::conversions::to_string_t (light_id)) }, - { U("type"), web::json::value::number ((int)IOglTF::FLOAT_MAT4) } - }) ; - techniqueParameters [name + utility::conversions::to_string_t (i) + U("FallOffAngle")] =web::json::value::object ({ - { U("type"), web::json::value::number ((int)IOglTF::FLOAT) }, - { U("value"), web::json::value::number (DEG2RAD (pLight->OuterAngle)) } - }) ; - techniqueParameters [name + utility::conversions::to_string_t (i) + U("FallOffExponent")] =web::json::value::object ({ - { U("type"), web::json::value::number ((int)IOglTF::FLOAT) }, - { U("value"), web::json::value::number ((double)0.) } - }) ; + auto &inverseVal = techniqueParameters [name + std::to_string (i) + ("InverseTransform")] ; + inverseVal[("semantic")] = (("MODELVIEWINVERSE")); + inverseVal[("node")] = (light_id); + inverseVal[("type")] = ((int)IOglTF::FLOAT_MAT4); + + auto &falloffVal = techniqueParameters [name + std::to_string(i) + ("FallOffAngle")]; + falloffVal[("type")] = ((int)IOglTF::FLOAT); + falloffVal[("value")] = (DEG2RAD (pLight->OuterAngle)); + + auto &falloffExpoVal = techniqueParameters [name + std::to_string (i) + ("FallOffExponent")]; + falloffExpoVal[("type")] = ((int)IOglTF::FLOAT); + falloffExpoVal[("value")] = 0.; } } } } -void gltfWriter::TechniqueParameters (FbxNode *pNode, web::json::value &techniqueParameters, web::json::value &attributes, web::json::value &accessors, bool bHasMaterial) { - for ( const auto &iter : attributes.as_object () ) { - utility::string_t name =iter.first ; +void gltfWriter::TechniqueParameters (FbxNode *pNode, Json::Value &techniqueParameters, Json::Value &attributes, Json::Value &accessors, bool bHasMaterial) { + auto memberNames = attributes.getMemberNames(); + for ( const auto &memberName : memberNames ) { + auto name = memberName; std::transform (name.begin (), name.end (), name.begin (), ::tolower) ; - //std::replace (name.begin (), name.end (), U('_'), U('x')) ; - name.erase (std::remove (name.begin (), name.end (), U('_')), name.end ()) ; - utility::string_t upperName (iter.first) ; + //std::replace (name.begin (), name.end (), ('_'), ('x')) ; + name.erase (std::remove (name.begin (), name.end (), ('_')), name.end ()) ; + std::string upperName (memberName) ; std::transform (upperName.begin (), upperName.end (), upperName.begin (), ::toupper) ; - web::json::value accessor =accessors [iter.second.as_string ()] ; - if ( !bHasMaterial && utility::details::limitedCompareTo (name, U("texcoord")) == 0 ) + Json::Value accessor =accessors [attributes[memberName].asString ()] ; + if ( !bHasMaterial && utility::details::limitedCompareTo (name, ("texcoord")) == 0 ) continue ; - techniqueParameters [name] =web::json::value::object ({ - { U("semantic"), web::json::value::string (upperName) }, - { U("type"), web::json::value::number ((int)IOglTF::techniqueParameters (accessor [U("type")].as_string ().c_str (), accessor [U("componentType")].as_integer ())) } - }) ; + auto &val = techniqueParameters [name]; + val[("semantic")] = (upperName); + val[("type")] = ((int)IOglTF::techniqueParameters (accessor [("type")].asString ().c_str (), accessor [("componentType")].asInt ())); } } -web::json::value gltfWriter::WriteTechnique (FbxNode *pNode, FbxSurfaceMaterial *pMaterial, web::json::value &techniqueParameters) { +Json::Value gltfWriter::WriteTechnique (FbxNode *pNode, FbxSurfaceMaterial *pMaterial, Json::Value &techniqueParameters) { // The FBX SDK does not have such attribute. At best, it is an attribute of a Shader FX, CGFX or HLSL. - web::json::value commonProfile =web::json::value::object ({{ U("doubleSided"), web::json::value::boolean (false) }}) ; + Json::Value commonProfile ; + commonProfile[("doubleSided")] = false ; if ( pMaterial != nullptr ) - commonProfile [U("lightingModel")] =web::json::value::string (LighthingModel (pMaterial)) ; + commonProfile [("lightingModel")] =(LighthingModel (pMaterial)) ; else - commonProfile [U("lightingModel")] =web::json::value::string (U("Unknown")) ; + commonProfile [("lightingModel")] =(("Unknown")) ; if ( _uvSets.size () ) { - commonProfile [U("texcoordBindings")] =web::json::value::object () ; + commonProfile [("texcoordBindings")] ; for ( auto iter : _uvSets ) { - utility::string_t key (iter.first) ; - std::string::size_type i =key.find (U("Color")) ; + std::string key (iter.first) ; + std::string::size_type i =key.find (("Color")) ; if ( i != std::string::npos ) key.erase (i, 5) ; std::transform (key.begin (), key.end (), key.begin (), ::tolower) ; - commonProfile [U("texcoordBindings")] [key] =web::json::value::string (iter.second) ; + commonProfile [("texcoordBindings")] [key] =(iter.second) ; } } - /*commonProfile [U("parameters")] =web::json::value::array () ; + /*commonProfile [("parameters")] =Json::Value::array () ; for ( const auto &iter : techniqueParameters.as_object () ) { - if ( ( utility::details::limitedCompareTo (iter.first, U("position")) != 0 - && utility::details::limitedCompareTo (iter.first, U("normal")) != 0 - && utility::details::limitedCompareTo (iter.first, U("texcoord")) != 0) - || iter.first == U("normalMatrix") + if ( ( utility::details::limitedCompareTo (iter.first, ("position")) != 0 + && utility::details::limitedCompareTo (iter.first, ("normal")) != 0 + && utility::details::limitedCompareTo (iter.first, ("texcoord")) != 0) + || iter.first == ("normalMatrix") ) - commonProfile [U("parameters")] [commonProfile [U("parameters")].size ()] =web::json::value::string (iter.first) ; + commonProfile [("parameters")] [commonProfile [("parameters")].size ()] =(iter.first) ; - web::json::value param =iter.second ; - if ( param [U("type")].as_integer () == IOglTF::SAMPLER_2D ) { + Json::Value param =iter.second ; + if ( param [("type")].asInt () == IOglTF::SAMPLER_2D ) { // todo: } }*/ - web::json::value attributes =web::json::value::object () ; - for ( const auto &iter : techniqueParameters.as_object () ) { - if ( utility::details::limitedCompareTo (iter.first, U("position")) == 0 - || (utility::details::limitedCompareTo (iter.first, U("normal")) == 0 && iter.first != U("normalMatrix")) - || (utility::details::limitedCompareTo (iter.first, U("texcoord")) == 0 && pMaterial != nullptr) + Json::Value attributes ; + auto memberNames = techniqueParameters.getMemberNames(); + for ( const auto &name : memberNames ) { + if ( utility::details::limitedCompareTo (name, ("position")) == 0 + || (utility::details::limitedCompareTo (name, ("normal")) == 0 && name != ("normalMatrix")) + || (utility::details::limitedCompareTo (name, ("texcoord")) == 0 && pMaterial != nullptr) ) - attributes [utility::string_t (U("a_")) + iter.first] =web::json::value::string (iter.first) ; + attributes ["a_" + name] =(name) ; } - web::json::value instanceProgram=web::json::value::object () ; - instanceProgram [U("attributes")] =attributes ; - instanceProgram [U("program")] =web::json::value::string (createUniqueName (utility::string_t (U("program")), 0)) ; // Start with 0, but will increase based on own many are yet registered - instanceProgram [U("uniforms")] =web::json::value::object () ; - for ( const auto &iter : techniqueParameters.as_object () ) { - if ( ( utility::details::limitedCompareTo (iter.first, U("position")) != 0 - && utility::details::limitedCompareTo (iter.first, U("normal")) != 0 - && utility::details::limitedCompareTo (iter.first, U("texcoord")) != 0) - || iter.first == U("normalMatrix") + Json::Value instanceProgram ; + instanceProgram [("attributes")] =attributes ; + instanceProgram [("program")] =(createUniqueName (std::string (("program")), 0)) ; // Start with 0, but will increase based on own many are yet registered + instanceProgram [("uniforms")] ; + for ( const auto &name : memberNames ) { + if ( ( utility::details::limitedCompareTo (name, ("position")) != 0 + && utility::details::limitedCompareTo (name, ("normal")) != 0 + && utility::details::limitedCompareTo (name, ("texcoord")) != 0) + || name == ("normalMatrix") ) - instanceProgram [U("uniforms")] [utility::string_t (U("u_")) + iter.first] =web::json::value::string (iter.first) ; + instanceProgram [("uniforms")] ["u_" + name] =(name) ; } - web::json::value techStatesEnable =web::json::value::array () ; + Json::Value techStatesEnable( Json::arrayValue ) ; if ( pNode->mCullingType == FbxNode::ECullingType::eCullingOff ) - techStatesEnable [techStatesEnable.size ()] =web::json::value::number ((int)IOglTF::CULL_FACE) ; + techStatesEnable [techStatesEnable.size ()] =((int)IOglTF::CULL_FACE) ; // TODO: should it always be this way? - techStatesEnable [techStatesEnable.size ()] =web::json::value::number ((int)IOglTF::DEPTH_TEST) ; + techStatesEnable [techStatesEnable.size ()] =((int)IOglTF::DEPTH_TEST) ; - web::json::value techStates =web::json::value::object () ; - techStates [U("enable")] =techStatesEnable ; + Json::Value techStates ; + techStates [("enable")] =techStatesEnable ; // TODO: needs to be implemented - //techStates [U("functions")] = + //techStates [("functions")] = - web::json::value technique =web::json::value::object () ; - technique [U("parameters")] =techniqueParameters ; - //technique [U("passes")] =web::json::value::object ({{ U("defaultPass"), techniquePass }}) ; - technique [U("program")] =instanceProgram [U("program")] ; - technique [U("states")] =techStates ; - technique [U("attributes")] =instanceProgram [U("attributes")] ; - technique [U("uniforms")] =instanceProgram [U("uniforms")] ; + Json::Value technique ; + technique [("parameters")] =techniqueParameters ; + //technique [("passes")] =Json::Value::object ({{ ("defaultPass"), techniquePass }}) ; + technique [("program")] =instanceProgram [("program")] ; + technique [("states")] =techStates ; + technique [("attributes")] =instanceProgram [("attributes")] ; + technique [("uniforms")] =instanceProgram [("uniforms")] ; - technique [U("extras")] =commonProfile ; + technique [("extras")] =commonProfile ; return (technique) ; } diff --git a/IO-glTF/gltfWriter-Texture.cpp b/IO-glTF/gltfWriter-Texture.cpp index 3b776cc..45348cc 100644 --- a/IO-glTF/gltfWriter-Texture.cpp +++ b/IO-glTF/gltfWriter-Texture.cpp @@ -26,25 +26,25 @@ namespace _IOglTF_NS_ { //FbxLayerElementTexture* texturesLayer =pNode->GetMesh ()->GetLayer (0)->GetTextures (FbxLayerElement::eTextureDiffuse) ; //FbxLayerElementArrayTemplate &arrayTextures =texturesLayer->GetDirectArray() ; //for ( int j = 0; j < arrayTextures.GetCount (); j++ ) -// ucout << U("\t ") << j << (".- ") << arrayTextures.GetAt (j)->GetName () << std::endl -// << U("\t ") << j << (".- ") << ((FbxFileTexture *)arrayTextures.GetAt (j))->GetFileName () << std::endl; +// std::cout << ("\t ") << j << (".- ") << arrayTextures.GetAt (j)->GetName () << std::endl +// << ("\t ") << j << (".- ") << ((FbxFileTexture *)arrayTextures.GetAt (j))->GetFileName () << std::endl; -web::json::value gltfWriter::WriteTexture (FbxTexture *pTexture) { - utility::string_t name =utility::conversions::to_string_t (pTexture->GetNameWithoutNameSpacePrefix ().Buffer ()) ; - utility::string_t uri =utility::conversions::to_string_t (FbxCast (pTexture)->GetRelativeFileName ()) ; - web::json::value image =web::json::value::object ({{ - name, web::json::value::object ({ - { U("name"), web::json::value::string (name) }, - { U("uri"), web::json::value::string (uri) } - }) } - }) ; +Json::Value gltfWriter::WriteTexture (FbxTexture *pTexture) { + std::string name =(pTexture->GetNameWithoutNameSpacePrefix ().Buffer ()) ; + std::string uri =(FbxCast (pTexture)->GetRelativeFileName ()) ; + Json::Value ret; + auto &image = ret["images"]; + auto &namedImage = image[name]; + namedImage[("name")] = (name) ; + namedImage[("uri")] = (uri) ; + if ( GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_EMBEDMEDIA, false) ) { // data:[][;charset=][;base64], FbxString imageFile =FbxCast (pTexture)->GetFileName () ; - image [name] [U("uri")] =web::json::value::string (IOglTF::dataURI (utility::conversions::to_string_t (imageFile.Buffer ()))) ; + image [name] [("uri")] =(IOglTF::dataURI ((imageFile.Buffer ()))) ; } /*else*/ if ( GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_COPYMEDIA, false) ) { - FbxString path =FbxPathUtils::GetFolderName (utility::conversions::to_utf8string (_fileName).c_str ()) ; + FbxString path =FbxPathUtils::GetFolderName ((_fileName).c_str ()) ; #if defined(_WIN32) || defined(_WIN64) path +="\\" ; #else @@ -56,41 +56,34 @@ web::json::value gltfWriter::WriteTexture (FbxTexture *pTexture) { dst << src.rdbuf () ; } - utility::string_t texName =createTextureName (pTexture->GetNameWithoutNameSpacePrefix ()) ; - utility::string_t samplerName =createSamplerName (pTexture->GetNameWithoutNameSpacePrefix ()) ; - web::json::value textureDef =web::json::value::object ({ - { U("name"), web::json::value::string (texName) }, - { U("format"), web::json::value::number ((int)IOglTF::RGBA) }, // todo - { U("internalFormat"), web::json::value::number ((int)IOglTF::RGBA) }, // todo - { U("sampler"), web::json::value::string (samplerName) }, // todo do I need one everytime - { U("source"), web::json::value::string (name) }, - { U("target"), web::json::value::number ((int)IOglTF::TEXTURE_2D) }, - { U("type"), web::json::value::number ((int)IOglTF::UNSIGNED_BYTE) } // todo - }) ; - - web::json::value texture =web::json::value::object ({{ texName, textureDef }}) ; + std::string texName =createTextureName (pTexture->GetNameWithoutNameSpacePrefix ()) ; + std::string samplerName =createSamplerName (pTexture->GetNameWithoutNameSpacePrefix ()) ; + + auto &textureDef = ret["textures"][texName]; + textureDef[("name")] = (texName); + textureDef[("format")] = ((int)IOglTF::RGBA); + textureDef[("internalFormat")] = ((int)IOglTF::RGBA); + textureDef[("sampler")] = (samplerName); // todo do I need one everytime + textureDef[("source")] = (name); + textureDef[("target")] = ((int)IOglTF::TEXTURE_2D) ; + textureDef[("type")] = ((int)IOglTF::UNSIGNED_BYTE) ; //TODO: Shall try to find a similar sampler defined already vs create one each time? - web::json::value samplerDef =web::json::value::object ({ - { U("name"), web::json::value::string (samplerName) }, - { U("magFilter"), web::json::value::number ((int)IOglTF::LINEAR) }, - { U("minFilter"), web::json::value::number ((int)IOglTF::LINEAR_MIPMAP_LINEAR) }, - { U("wrapS"), web::json::value::number ((int)(pTexture->WrapModeU.Get () == FbxTexture::eRepeat ? IOglTF::REPEAT : IOglTF::CLAMP_TO_EDGE)) }, - { U("wrapT"), web::json::value::number ((int)(pTexture->WrapModeV.Get () == FbxTexture::eRepeat ? IOglTF::REPEAT : IOglTF::CLAMP_TO_EDGE)) } - }) ; + auto &samplerDef = ret["samplers"][samplerName]; + samplerDef[("name")] = (samplerName); + samplerDef[("magFilter")] = ((int)IOglTF::LINEAR) ; + samplerDef[("minFilter")] = ((int)IOglTF::LINEAR_MIPMAP_LINEAR) ; + samplerDef[("wrapS")] = ((int)(pTexture->WrapModeU.Get () == FbxTexture::eRepeat ? IOglTF::REPEAT : IOglTF::CLAMP_TO_EDGE)) ; + samplerDef[("wrapT")] = ((int)(pTexture->WrapModeV.Get () == FbxTexture::eRepeat ? IOglTF::REPEAT : IOglTF::CLAMP_TO_EDGE)) ; - return (web::json::value::object ({ - { U("images"), image }, - { U("textures"), web::json::value::object ({{ texName, textureDef }}) }, - { U("samplers"), web::json::value::object ({{ samplerName, samplerDef }}) } - })) ; + return ret; } -web::json::value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMaterial *pMaterial, web::json::value ¶ms) { +Json::Value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMaterial *pMaterial, Json::Value ¶ms) { return false ; } -//web::json::value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMaterial *pMaterial, web::json::value ¶ms) { +//Json::Value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMaterial *pMaterial, Json::Value ¶ms) { // // Export textures used by the mesh material // //for ( int textureTypeIndex =(int)FbxLayerElement::sTypeTextureStartIndex ; textureTypeIndex <= (int)FbxLayerElement::sTypeTextureEndIndex ; textureTypeIndex++ ) { // //FbxLayerElementTexture *pLayerElementTexture =pLayer->GetTextures ((FbxLayerElement::EType)textureTypeIndex) ; @@ -108,7 +101,7 @@ web::json::value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMat // for ( int k =0 ; k < nbTexture ; k++ ) { // FbxTexture *pTexture =pLayeredTexture->GetSrcObject (k) ; // if ( pTexture ) { -// utility::string_t name =U("texture_") + utility::conversions::to_string_t (pTexture->GetNameWithoutNameSpacePrefix ().Buffer ()) ; +// std::string name =("texture_") + utility::conversions::to_string_t (pTexture->GetNameWithoutNameSpacePrefix ().Buffer ()) ; // //texture_id = getTextureName (texture, True) // //material_params [binding_types [str (material_property.GetName ())]] = texture_id // } @@ -120,7 +113,7 @@ web::json::value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMat // for ( int j =0 ; j < nbLayeredTexture ; j++ ) { // FbxTexture *pTexture =materialProperty.GetSrcObject (j) ; // if ( pTexture ) { -// utility::string_t name =U("texture_") + utility::conversions::to_string_t (pTexture->GetNameWithoutNameSpacePrefix ().Buffer ()) ; +// std::string name =("texture_") + utility::conversions::to_string_t (pTexture->GetNameWithoutNameSpacePrefix ().Buffer ()) ; // //texture_id = getTextureName (texture, True) // //material_params [binding_types [str (material_property.GetName ())]] = texture_id // } @@ -131,7 +124,7 @@ web::json::value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMat //} /* -web::json::value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, web::json::value &materials, web::json::value &techniques) { +Json::Value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, Json::Value &materials, Json::Value &techniques) { // Export textures used by the mesh int nbLayer =pMesh->GetLayerCount () ; for ( int layerIndex =0 ; layerIndex < nbLayer; layerIndex++ ) { @@ -163,34 +156,34 @@ web::json::value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, web::json::va pTexture =FbxCast (textureArray [texIndex]) ; if ( !pTexture ) continue ; - utility::string_t name =utility::conversions::to_string_t (pTexture->GetNameWithoutNameSpacePrefix ().Buffer ()) ; - utility::string_t uri =utility::conversions::to_string_t (pTexture->GetRelativeFileName ()) ; - web::json::value image =web::json::value::object ({{ - name, web::json::value::object ({ - { U("name"), web::json::value::string (name) }, - { U("uri"), web::json::value::string (uri) } + std::string name =utility::conversions::to_string_t (pTexture->GetNameWithoutNameSpacePrefix ().Buffer ()) ; + std::string uri =utility::conversions::to_string_t (pTexture->GetRelativeFileName ()) ; + Json::Value image =Json::Value::object ({{ + name, Json::Value::object ({ + { ("name"), (name) }, + { ("uri"), (uri) } }) } }) ; - utility::string_t texName (U("texture_") + name) ; - web::json::value textureDef =web::json::value::object ({ - { U("name"), web::json::value::string (texName) }, - // { U("format"), web::json::value::string (uri) }, - // { U("internalFormat"), web::json::value::string (uri) }, - // { U("sampler"), web::json::value::string (uri) }, - { U("source"), web::json::value::string (name) }, - // { U("target"), web::json::value::string (uri) }, - { U("type"), web::json::value::number ((int)IOglTF::TEXTURE_2D) } + std::string texName (("texture_") + name) ; + Json::Value textureDef =Json::Value::object ({ + { ("name"), (texName) }, + // { ("format"), (uri) }, + // { ("internalFormat"), (uri) }, + // { ("sampler"), (uri) }, + { ("source"), (name) }, + // { ("target"), (uri) }, + { ("type"), ((int)IOglTF::TEXTURE_2D) } }) ; - web::json::value texture =web::json::value::object ({{ texName, textureDef }}) ; + Json::Value texture =Json::Value::object ({{ texName, textureDef }}) ; - web::json::value samplerDef =web::json::value::object ({ - { U("name"), web::json::value::string (texName) }, - { U("magFilter"), web::json::value::number ((int)IOglTF::LINEAR) }, - { U("minFilter"), web::json::value::number ((int)IOglTF::LINEAR_MIPMAP_LINEAR) }, - { U("wrapS"), web::json::value::number ((int)(pTexture->WrapModeU.Get () == FbxTexture::eRepeat ? IOglTF::REPEAT : IOglTF::CLAMP_TO_EDGE)) }, - { U("wrapT"), web::json::value::number ((int)(pTexture->WrapModeV.Get () == FbxTexture::eRepeat ? IOglTF::REPEAT : IOglTF::CLAMP_TO_EDGE)) } + Json::Value samplerDef =Json::Value::object ({ + { ("name"), (texName) }, + { ("magFilter"), ((int)IOglTF::LINEAR) }, + { ("minFilter"), ((int)IOglTF::LINEAR_MIPMAP_LINEAR) }, + { ("wrapS"), ((int)(pTexture->WrapModeU.Get () == FbxTexture::eRepeat ? IOglTF::REPEAT : IOglTF::CLAMP_TO_EDGE)) }, + { ("wrapT"), ((int)(pTexture->WrapModeV.Get () == FbxTexture::eRepeat ? IOglTF::REPEAT : IOglTF::CLAMP_TO_EDGE)) } }) ; @@ -200,7 +193,7 @@ web::json::value gltfWriter::WriteTextureBindings (FbxMesh *pMesh, web::json::va return (false) ; }*/ -//web::json::value gltfWriter::WriteTextures (FbxMesh *pMesh) { +//Json::Value gltfWriter::WriteTextures (FbxMesh *pMesh) { // // Export textures used by the mesh // FbxNode *pNode =pMesh->GetNode () ; // int nbLayer =pMesh->GetLayerCount () ; diff --git a/IO-glTF/gltfWriter.cpp b/IO-glTF/gltfWriter.cpp index 17a0cd6..4baf740 100644 --- a/IO-glTF/gltfWriter.cpp +++ b/IO-glTF/gltfWriter.cpp @@ -23,29 +23,30 @@ #ifdef _DEBUG #include "JsonPrettify.h" #endif - +#include #include #define _DEBUG_VERBOSE 1 namespace _IOglTF_NS_ { //----------------------------------------------------------------------------- -web::json::value &MergeJsonObjects (web::json::value &a, const web::json::value &b) { - if ( b.is_null () || !b.is_object () ) +Json::Value &MergeJsonObjects (Json::Value &a, const Json::Value &b) { + if ( b.isNull () || !b.isObject () ) return (a) ; - for ( const auto &iter : b.as_object () ) { - if ( !a.has_field (iter.first) ) { - a [iter.first] =iter.second ; + auto memberNames = b.getMemberNames(); + for ( const auto &name : memberNames ) { + if ( !a.isMember (name) ) { + a [name] =b[name] ; } else { - MergeJsonObjects (a [iter.first], b.at (iter.first)) ; + MergeJsonObjects (a [name], b[(name)]) ; } } return (a) ; } -utility::string_t GetJsonObjectKeyAt (web::json::value &a, int i) { - const auto &b =a.as_object () ; - return (b.begin ()->first) ; +std::string GetJsonObjectKeyAt (Json::Value &a, int i) { + const auto &b =a.getMemberNames() ; + return (b.front()) ; } //----------------------------------------------------------------------------- @@ -78,12 +79,22 @@ gltfWriter::~gltfWriter () { bool gltfWriter::FileCreate (char *pFileName) { FbxString fileName =FbxPathUtils::Clean (pFileName) ; - _fileName =utility::conversions::to_string_t (fileName.Buffer ()) ; + _fileName = (fileName.Buffer ()) ; - //utility::string_t path =_GLTF_NAMESPACE_::GetModulePath () ; - utility::string_t path =utility::conversions::to_string_t ((const char *)FbxGetApplicationDirectory ()) ; - utility::ifstream_t input (path + U("glTF-1-0.json"), std::ios::in) ; - _json =web::json::value::parse (input) ; + //std::string path =_GLTF_NAMESPACE_::GetModulePath () ; + std::string path = ((const char *)FbxGetApplicationDirectory ()) ; + std::ifstream input (path + ("glTF-1-0.json"), std::ios::in) ; + + Json::Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + Json::Reader reader( features ); + try { + reader.parse( input, _json, false ); + } + catch ( const std::exception &ex ) { + std::cout << ex.what() << std::endl; + } input.close () ; if ( !FbxPathUtils::Create (FbxPathUtils::GetFolderName (fileName)) ) @@ -97,16 +108,18 @@ bool gltfWriter::FileCreate (char *pFileName) { bool gltfWriter::FileClose () { PrepareForSerialization () ; #ifdef _DEBUG - JsonPrettify prettify (_json) ; - prettify.serialize (_gltf) ; + Json::StyledWriter writer; + writer.write( _json ); #else - _json.serialize (_gltf) ; + Json::FastWriter writer; + auto temp = writer.write( _json ); + _gltf.write( temp.c_str(), temp.length() ) ; #endif _gltf.close () ; // If media saved in file, gltfWriter::PostprocessScene / gltfWriter::WriteBuffer should have embed the data already if ( !GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_EMBEDMEDIA, false) ) { - FbxString fileName (utility::conversions::to_utf8string (_fileName).c_str ()) ; + FbxString fileName ( (_fileName).c_str ()) ; #if defined(_WIN32) || defined(_WIN64) fileName =FbxPathUtils::GetFolderName (fileName) + "\\" + FbxPathUtils::GetFileName (fileName, false) + ".bin" ; #else @@ -278,9 +291,9 @@ void gltfWriter::PreprocessNodeRecursive (FbxNode *pNode) { // pMesh =FbxCast (lConverter.Triangulate (pMesh, true)); bool gltfWriter::PostprocessScene (FbxScene &scene) { - /*web::json::value val =WriteAmbientLight (pScene) ; + /*Json::Value val =WriteAmbientLight (pScene) ; for ( const auto &iter : val.as_object () ) - _json [U("lights")] [iter.first] =iter.second ; + _json [("lights")] [iter.first] =iter.second ; */ //if ( GetIOSettings ()->GetBoolProp (IOSN_FBX_GLTF_COPYMEDIA, false) ) { //#if defined(_WIN32) || defined(_WIN64) @@ -288,7 +301,7 @@ bool gltfWriter::PostprocessScene (FbxScene &scene) { //#else // FbxString path =FbxPathUtils::GetFolderName (utility::conversions::to_utf8string (_fileName).c_str ()) + "/" ; //#endif - // for ( const auto &iter : _json [U("images")].as_object () ) { + // for ( const auto &iter : _json [("images")].as_object () ) { // } // //} @@ -332,7 +345,7 @@ void gltfWriter::PrepareForSerialization () { // auto k =iter->first ; // auto v =iter->second ; - // auto key =k.as_string () ; + // auto key =k.asString () ; // auto value =v.to_string () ; // wcout << key << L" : " << value << " (" << JsonValueTypeToString (v.type ()) << ")" << endl; @@ -340,7 +353,7 @@ void gltfWriter::PrepareForSerialization () { } //----------------------------------------------------------------------------- -bool gltfWriter::recordId (FbxUInt64 uniqid, utility::string_t id) { +bool gltfWriter::recordId (FbxUInt64 uniqid, std::string id) { if ( !isKnownId (uniqid) ) { _IDs [uniqid] =id ; return (false) ; @@ -352,129 +365,137 @@ bool gltfWriter::isKnownId (FbxUInt64 uniqid) { return (_IDs.find (uniqid) != _IDs.end ()) ; } -bool gltfWriter::isKnownId (utility::string_t id) { +bool gltfWriter::isKnownId (std::string id) { //return (std::find (_registeredIDs.begin (), _registeredIDs.end (), id) != _registeredIDs.end ()) ; - auto findResult =std::find_if (std::begin (_IDs), std::end (_IDs), [&] (const std::pair &pair) { + auto findResult =std::find_if (std::begin (_IDs), std::end (_IDs), [&] (const std::pair &pair) { return (pair.second == id) ; }) ; return (findResult != std::end (_IDs)) ; } -utility::string_t gltfWriter::nodeId (FbxNode *pNode, bool bNodeAttribute /*=false*/, bool bRecord /*=false*/) { +std::string gltfWriter::nodeId (FbxNode *pNode, bool bNodeAttribute /*=false*/, bool bRecord /*=false*/) { FbxUInt64 id =bNodeAttribute && pNode->GetNodeAttribute () != nullptr ? pNode->GetNodeAttribute ()->GetUniqueID () : pNode->GetUniqueID () ; if ( isKnownId (id) ) return (_IDs [id]) ; - utility::string_t name =utility::conversions::to_string_t ( - bNodeAttribute && pNode->GetNodeAttribute () != nullptr ? pNode->GetNodeAttribute ()->GetName () : pNode->GetName () - ) ; - if ( name == U("") ) - name =utility::conversions::to_string_t (pNode->GetTypeName ()) ; + std::string name = bNodeAttribute && pNode->GetNodeAttribute () != nullptr ? pNode->GetNodeAttribute ()->GetName () : pNode->GetName (); + if ( name == ("") ) + name =(pNode->GetTypeName ()) ; //if ( isKnownId (name) ) // Comment if it should be consistent? - name +=U("_") + utility::conversions::to_string_t ((int)id) ; + name +=("_") + std::to_string((int)id) ; if ( bRecord ) recordId (id, name) ; return (name) ; } -utility::string_t gltfWriter::registerName (utility::string_t name) { +std::string gltfWriter::registerName (std::string name) { if ( !isNameRegistered (name) ) _registeredNames.push_back (name) ; return (name) ; } -bool gltfWriter::isNameRegistered (utility::string_t id) { +bool gltfWriter::isNameRegistered (std::string id) { return (std::find (_registeredNames.begin (), _registeredNames.end (), id) != _registeredNames.end ()) ; } -utility::string_t gltfWriter::createUniqueName (utility::string_t type, FbxUInt64 id) { +std::string gltfWriter::createUniqueName (std::string type, FbxUInt64 id) { for ( ;; id++ ) { - utility::string_t buffer =utility::conversions::to_string_t ((int)id) ; - utility::string_t uid (type) ; - uid +=U("_") + buffer ; + std::string buffer =utility::conversions::to_string_t ((int)id) ; + std::string uid (type) ; + uid +=("_") + buffer ; if ( !isNameRegistered (uid) ) return (registerName (uid)) ; } _ASSERTE (false) ; - return (U("error")) ; + return (("error")) ; } //----------------------------------------------------------------------------- -web::json::value gltfWriter::WriteSceneNodeRecursive (FbxNode *pNode, FbxPose *pPose /*=nullptr*/, bool bRoot /*=false*/) { +Json::Value gltfWriter::WriteSceneNodeRecursive (FbxNode *pNode, FbxPose *pPose /*=nullptr*/, bool bRoot /*=false*/) { //if ( !WriteSceneNode (pNode, pPose) ) // //return (GetStatus ().SetCode (FbxStatus::eFailure, "Could not export node " + pNode->GetName () + "!"), false) ; // return (false) ; #ifdef _DEBUG_VERBOSE - utility::string_t name =utility::conversions::to_string_t (pNode->GetNameOnly ().Buffer ()) ; - _path.push_back (name) ; + std::string name =(pNode->GetNameOnly ().Buffer ()) ; + //_path.push_back (name) ; #endif - web::json::value node =WriteSceneNode (pNode, pPose) ; - utility::string_t nodeName, meshName ; - if ( !node.is_null () ) { - nodeName =GetJsonFirstKey (node [U("nodes")]) ; - if ( !bRoot && node [U("meshes")].size () - //&& node [U("nodes")] [nodeName] [U("children")].size () == 0 + Json::Value node =WriteSceneNode (pNode, pPose) ; + std::string nodeName, meshName ; + if ( !node.isNull () ) { + nodeName =GetJsonFirstKey (node [("nodes")]) ; + static Json::Value sIdentity4Mat( Json::arrayValue ) ; + static bool sIdentity4MatInitialized = false; + if( ! sIdentity4MatInitialized ) { + std::array identity{ 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. }; + auto i{0}; + for( auto val : identity ) + sIdentity4Mat[i++] = val; + sIdentity4MatInitialized = true; + } + auto &mat = node [("nodes")] [nodeName] [("matrix")]; + if ( !bRoot && node [("meshes")].size () + //&& node [("nodes")] [nodeName] [("children")].size () == 0 && pNode->GetChildCount () == 0 - && node [U("nodes")] [nodeName] [U("matrix")].serialize () == IOglTF::Identity4.serialize () + && sIdentity4Mat == mat ) { - // meshName =GetJsonFirstKey (node [U("meshes")]) ; - node [U("nodes")] =web::json::value::object () ; + // meshName =GetJsonFirstKey (node [("meshes")]) ; + node [("nodes")] ; } MergeJsonObjects (_json, node) ; if ( bRoot ) { - utility::string_t szName (utility::conversions::to_string_t (pNode->GetScene ()->GetName ())) ; - size_t pos =_json [U("scenes")] [szName] [U("nodes")].size () ; - _json [U("scenes")] [szName] [U("nodes")] [pos] =web::json::value::string (nodeName) ; + std::string szName ((pNode->GetScene ()->GetName ())) ; + uint32_t pos =_json [("scenes")] [szName] [("nodes")].size () ; + _json [("scenes")] [szName] [("nodes")] [pos] =(nodeName) ; } } #ifdef _DEBUG_VERBOSE //else { - // ucout << U(" !!! Null returned ( ") << name << U(" ) - ") ; - // for ( utility::string_t st : _path ) - // ucout << U(" << ") << st ; - // ucout << std::endl ; - // return (web::json::value::null ()) ; + // std::cout << (" !!! Null returned ( ") << name << (" ) - ") ; + // for ( std::string st : _path ) + // std::cout << (" << ") << st ; + // std::cout << std::endl ; + // return (Json::Value::null ()) ; //} #endif FbxNodeAttribute::EType enodeType =nodeType (pNode) ; for ( int i =0; i < pNode->GetChildCount () ; i++ ) { - web::json::value child =WriteSceneNodeRecursive (pNode->GetChild (i), pPose, bRoot && enodeType == FbxNodeAttribute::eUnknown) ; - if ( !child.is_null () && !node.is_null () ) { - utility::string_t key (U("nodes")), key2 (U("children")) ; - if ( !child.is_null () && child [U("nodes")].size () == 0 - && child [U("meshes")].size () != 0 + Json::Value child =WriteSceneNodeRecursive (pNode->GetChild (i), pPose, bRoot && enodeType == FbxNodeAttribute::eUnknown) ; + if ( !child.isNull () && !node.isNull () ) { + std::string key (("nodes")), key2 (("children")) ; + if ( !child.isNull () && child [("nodes")].size () == 0 + && child [("meshes")].size () != 0 ) - key =key2 =U("meshes") ; - utility::string_t childName (GetJsonFirstKey (child [key])) ; - size_t pos =_json [U("nodes")] [nodeName] [key2].size () ; + key =key2 =("meshes") ; + std::string childName (GetJsonFirstKey (child [key])) ; + uint32_t pos =_json [("nodes")] [nodeName] [key2].size () ; //if ( std::find ( - // _json [U("nodes")] [nodeName] [key2].as_array ().begin (), - // _json [U("nodes")] [nodeName] [key2].as_array ().end (), - // web::json::value::string (childName) - // ) != _json [U("nodes")] [nodeName] [key2].as_array ().end () + // _json [("nodes")] [nodeName] [key2].as_array ().begin (), + // _json [("nodes")] [nodeName] [key2].as_array ().end (), + // (childName) + // ) != _json [("nodes")] [nodeName] [key2].as_array ().end () //) - // ucout << U(" yes ") << std::endl ; - _json [U("nodes")] [nodeName] [key2] [pos] =web::json::value::string (childName) ; + // std::cout << (" yes ") << std::endl ; + _json [("nodes")] [nodeName] [key2] [pos] =(childName) ; } } #ifdef _DEBUG_VERBOSE - _path.pop_back () ; + //_path.pop_back () ; #endif return (node) ; } -web::json::value gltfWriter::WriteSceneNode (FbxNode *pNode, FbxPose *pPose) { +Json::Value gltfWriter::WriteSceneNode (FbxNode *pNode, FbxPose *pPose) { - //utility::string_t id =nodeId (pNode) ; - //if ( _json [U("nodes")].has_field (id) ) { + //std::string id =nodeId (pNode) ; + //if ( _json [("nodes")].isMember (id) ) { // // This node was already exported, return only its name - // return (web::json::value::null ()) ; + // return (Json::Value::null ()) ; //} FbxNodeAttribute::EType enodeType =nodeType (pNode) ; @@ -482,40 +503,40 @@ web::json::value gltfWriter::WriteSceneNode (FbxNode *pNode, FbxPose *pPose) { //if ( FbxString (pNode->GetName ()) != FbxString ("RootNode") // && pNodeAttribute != nullptr //) - ucout << U("Warning: (") << utility::conversions::to_string_t (pNode->GetTypeName ()) - << U(" - ") << (int)enodeType - << U(") ") << utility::conversions::to_string_t (pNode->GetName ()) - << U(" not exported!") + std::cout << ("Warning: (") << (pNode->GetTypeName ()) + << (" - ") << (int)enodeType + << (") ") << (pNode->GetName ()) + << (" not exported!") << std::endl ; - return (web::json::value::null ()) ; + return (Json::Value( Json::nullValue )) ; } //FbxProperty cid =pNode->FindProperty ("COLLADA_ID") ; //FbxString sid =cid.IsValid () ? cid.Get () : FbxString ("") ; - //utility::string_t ff =utility::conversions::to_string_t (sid.Buffer ()) ; + //std::string ff =utility::conversions::to_string_t (sid.Buffer ()) ; - //utility::string_t id =nodeId (pNode) ; + //std::string id =nodeId (pNode) ; //if ( isIdRegistered (id) ) { - //// ucout << id << U(" ( ") << ff << U(" ) x") << std::endl ; - // return (web::json::value::null ()) ; + //// std::cout << id << (" ( ") << ff << (" ) x") << std::endl ; + // return (Json::Value::null ()) ; //} - ////ucout << id << U(" ( ") << ff << U(" ) ") << std::endl ; + ////std::cout << id << (" ( ") << ff << (" ) ") << std::endl ; #ifdef _DEBUG_VERBOSE - //for ( utility::string_t st : _path ) - // ucout << U(" << ") << st ; - //ucout << std::endl ; + //for ( std::string st : _path ) + // std::cout << (" << ") << st ; + //std::cout << std::endl ; #endif ExporterRouteFct fct =(*(_routes.find (enodeType))).second ; - web::json::value val =(this->*fct) (pNode) ; -// web::json::value val =WriteNull (pNode) ; + Json::Value val =(this->*fct) (pNode) ; +// Json::Value val =WriteNull (pNode) ; //for ( auto iter =val.as_object ().cbegin () ; iter != val.as_object ().cend () ; ++iter ) { - // //const utility::string_t &str =iter->first ; - // const web::json::value &v =iter->second ; + // //const std::string &str =iter->first ; + // const Json::Value &v =iter->second ; // for ( auto iter2 =v.as_object ().cbegin () ; iter2 != v.as_object ().cend () ; ++iter2 ) { - // const utility::string_t &id =iter2->first ; - // //ucout << id << std::endl ; + // const std::string &id =iter2->first ; + // //std::cout << id << std::endl ; // registerId (id) ; // } //} @@ -528,14 +549,14 @@ FbxNodeAttribute::EType gltfWriter::nodeType (FbxNode *pNode) { FbxNodeAttribute::EType nodeType =pNodeAttribute ? pNodeAttribute->GetAttributeType () : FbxNodeAttribute::eUnknown ; // Non paired node if ( pNodeAttribute == nullptr ) { - utility::string_t szType =utility::conversions::to_string_t (pNode->GetTypeName ()) ; - if ( szType == U("Null") ) + std::string szType = (pNode->GetTypeName ()) ; + if ( szType == ("Null") ) nodeType =FbxNodeAttribute::eNull ; } return (nodeType) ; } -web::json::value gltfWriter::GetTransform (FbxNode *pNode) { +Json::Value gltfWriter::GetTransform (FbxNode *pNode) { // Export the node's default transforms // If the mesh is a skin binded to a skeleton, the bind pose will include its transformations. @@ -569,52 +590,55 @@ web::json::value gltfWriter::GetTransform (FbxNode *pNode) { } FbxAMatrix::kDouble44 &r =thisLocal.Double44 () ; - std::vector ar ; + Json::Value ar( Json::arrayValue ) ; + auto k{0}; for ( int i =0 ; i < 4 ; i++ ) for ( int j =0 ; j < 4 ; j++ ) - ar.push_back (web::json::value::number (r [i] [j])) ; - return (web::json::value::array (ar)) ; + ar[k++] = ((r [i] [j])) ; + return (ar) ; } //----------------------------------------------------------------------------- -web::json::value gltfWriter::WriteNode (FbxNode *pNode) { - web::json::value nodeDef =web::json::value::object () ; +Json::Value gltfWriter::WriteNode (FbxNode *pNode) { + Json::Value nodeDef ; - utility::string_t id =nodeId (pNode, false, true) ; - nodeDef [U("name")] =web::json::value::string (id) ; + std::string id =nodeId (pNode, false, true) ; + nodeDef [("name")] =(id) ; - utility::string_t szType =utility::conversions::to_string_t (pNode->GetTypeName ()) ; + std::string szType =(pNode->GetTypeName ()) ; std::transform (szType.begin (), szType.end (), szType.begin (), ::tolower) ; // A floating-point 4x4 transformation matrix stored in column-major order. // A node will have either a matrix property defined or any combination of rotation, scale, and translation properties defined. - web::json::value nodeTransform =GetTransform (pNode) ; + Json::Value nodeTransform =GetTransform (pNode) ; //if ( !nodeTransform.is_boolean () || nodeTransform != true ) - nodeDef [U("matrix")] =nodeTransform ; - //nodeDef [U("rotation")] =web::json::value::array ({{ 1., 0., 0., 0. }}) ; - //nodeDef [U("scale")] =web::json::value::array ({{ 1., 1., 1. }}) ; - //nodeDef [U("translation")] =web::json::value::array ({{ 0., 0., 0. }}) ; + nodeDef [("matrix")] =nodeTransform ; + //nodeDef [("rotation")] =Json::Value::array ({{ 1., 0., 0., 0. }}) ; + //nodeDef [("scale")] =Json::Value::array ({{ 1., 1., 1. }}) ; + //nodeDef [("translation")] =Json::Value::array ({{ 0., 0., 0. }}) ; - nodeDef [U("children")] =web::json::value::array () ; - //nodeDef [U("instanceSkin")] = ; + nodeDef [("children")] =Json::Value( Json::arrayValue ) ; + //nodeDef [("instanceSkin")] = ; const FbxNodeAttribute *nodeAttribute =pNode->GetNodeAttribute () ; if ( nodeAttribute && nodeAttribute->GetAttributeType () == FbxNodeAttribute::eSkeleton ) { // The only difference between a node containing a nullptr and one containing a SKELETON is the property type JOINT. - nodeDef [U("jointName")] =web::json::value::string (U("JOINT")) ; + nodeDef [("jointName")] =(("JOINT")) ; } - //if ( szType == U("mesh") ) + //if ( szType == ("mesh") ) if ( pNode->GetNodeAttribute () && pNode->GetNodeAttribute ()->GetAttributeType () == FbxNodeAttribute::eMesh ) - nodeDef [U("meshes")] =web::json::value::array ({{ web::json::value (nodeId (pNode, true)) }}) ; - //if ( szType == U("camera") || szType == U("light") ) + nodeDef [("meshes")][0] = (nodeId (pNode, true)) ; + //if ( szType == ("camera") || szType == ("light") ) if ( pNode->GetNodeAttribute () && ( pNode->GetNodeAttribute ()->GetAttributeType () == FbxNodeAttribute::eCamera || pNode->GetNodeAttribute ()->GetAttributeType () == FbxNodeAttribute::eLight) ) - nodeDef [szType] =web::json::value::string (nodeId (pNode, true)) ; //nodeDef [U("camera")] nodeDef [U("light")] + nodeDef [szType] =(nodeId (pNode, true)) ; //nodeDef [("camera")] nodeDef [("light")] - return (web::json::value::object ({{ id, nodeDef }})) ; + Json::Value ret; + ret[id] = nodeDef; + return (ret) ; } diff --git a/IO-glTF/gltfWriter.h b/IO-glTF/gltfWriter.h index d1c0aae..52cfe16 100644 --- a/IO-glTF/gltfWriter.h +++ b/IO-glTF/gltfWriter.h @@ -22,11 +22,12 @@ #define _USE_MATH_DEFINES #include +#include "jsoncpp/json.h" -#define FBX_GLTF_EXPORTER U("FBX GLTF Exporter v1.0") -#define PROFILE_API U("WebGL") -#define PROFILE_VERSION U("1.0.3") -#define GLTF_VERSION U("1.0") +#define FBX_GLTF_EXPORTER ("FBX GLTF Exporter v1.0") +#define PROFILE_API ("WebGL") +#define PROFILE_VERSION ("1.0.3") +#define GLTF_VERSION ("1.0") #define DEG2RAD(a) a * M_PI / 180.0 #define MergeJsonObjects_(a, b) \ @@ -34,7 +35,7 @@ a [iter.first] =iter.second //#define MergeJsonFromRetObject(a, b) \ // { \ -// web::json::value b2 =b ; \ +// Json::Value b2 =b ; \ // for ( const auto &iter : b2.as_object () ) \ // a [iter.first] =iter.second ; \ // } @@ -44,25 +45,25 @@ namespace _IOglTF_NS_ { -web::json::value &MergeJsonObjects (web::json::value &a, const web::json::value &b) ; -utility::string_t GetJsonObjectKeyAt (web::json::value &a, int i =0) ; +Json::Value &MergeJsonObjects (Json::Value &a, const Json::Value &b) ; +std::string GetJsonObjectKeyAt (Json::Value &a, int i =0) ; #define GetJsonFirstKey(a) GetJsonObjectKeyAt(a) class gltfWriter : public FbxWriter { private: - utility::string_t _fileName ; - utility::ofstream_t _gltf ; + std::string _fileName ; + std::ofstream _gltf ; memoryStream _bin ; - web::json::value _json ; + Json::Value _json ; bool _writeDefaults ; double _samplingPeriod ; - std::map _IDs ; - std::vector _registeredNames ; - std::map _uvSets ; + std::map _IDs ; + std::vector _registeredNames ; + std::map _uvSets ; #ifdef _DEBUG - std::vector _path ; + std::vector _path ; #endif public: @@ -85,33 +86,33 @@ class gltfWriter : public FbxWriter { void PrepareForSerialization () ; protected: - bool recordId (FbxUInt64 uniqid, utility::string_t id) ; + bool recordId (FbxUInt64 uniqid, std::string id) ; bool isKnownId (FbxUInt64 uniqid) ; - bool isKnownId (utility::string_t id) ; + bool isKnownId (std::string id) ; public: - utility::string_t nodeId (FbxNode *pNode, bool bNodeAttribute =false, bool bRecord =false) ; + std::string nodeId (FbxNode *pNode, bool bNodeAttribute =false, bool bRecord =false) ; protected: - utility::string_t registerName (utility::string_t name) ; - bool isNameRegistered (utility::string_t id) ; + std::string registerName (std::string name) ; + bool isNameRegistered (std::string id) ; public: - utility::string_t createUniqueName (utility::string_t type, FbxUInt64 id) ; + std::string createUniqueName (std::string type, FbxUInt64 id) ; - inline utility::string_t createSamplerName (FbxString &szname) { return (U ("sampler_") + utility::conversions::to_string_t (szname.Buffer ())) ; } - inline utility::string_t createSamplerName (const char *pszName) { return (U ("sampler_") + utility::conversions::to_string_t (pszName)) ; } - inline utility::string_t createTextureName (FbxString &szname) { return (U("texture_") + utility::conversions::to_string_t (szname.Buffer ())) ; } - inline utility::string_t createTextureName (const char *pszName) { return (U("texture_") + utility::conversions::to_string_t (pszName)) ; } + inline std::string createSamplerName (FbxString &szname) { return (("sampler_") + std::string(szname.Buffer ())) ; } + inline std::string createSamplerName (const char *pszName) { return (("sampler_") + std::string(pszName)) ; } + inline std::string createTextureName (FbxString &szname) { return (("texture_") + std::string(szname.Buffer ())) ; } + inline std::string createTextureName (const char *pszName) { return (("texture_") + std::string(pszName)) ; } protected: - web::json::value WriteSceneNodeRecursive (FbxNode *pNode, FbxPose *pPose =nullptr, bool bRoot =false) ; - web::json::value WriteSceneNode (FbxNode *pNode, FbxPose *pPose =nullptr) ; + Json::Value WriteSceneNodeRecursive (FbxNode *pNode, FbxPose *pPose =nullptr, bool bRoot =false) ; + Json::Value WriteSceneNode (FbxNode *pNode, FbxPose *pPose =nullptr) ; FbxNodeAttribute::EType nodeType (FbxNode *pNode) ; bool IsGeometryNode (FbxNode *pNode) ; bool CheckMaterials (FbxNode *pNode) ; void PreprocessNodeRecursive (FbxNode *pNode) ; - web::json::value WriteNode (FbxNode *pNode) ; - web::json::value GetTransform (FbxNode *pNode) ; + Json::Value WriteNode (FbxNode *pNode) ; + Json::Value GetTransform (FbxNode *pNode) ; // The following list is json nodes generated by other json nodes // accessor / bufferView @@ -122,76 +123,76 @@ class gltfWriter : public FbxWriter { bool WriteBuffer () ; // camera double cameraYFOV (FbxCamera *pCamera) ; - web::json::value WriteCamera (FbxNode *pNode) ; + Json::Value WriteCamera (FbxNode *pNode) ; // light - void lightAttenuation (FbxLight *pLight, web::json::value &lightDef) ; - web::json::value WriteLight (FbxNode *pNode) ; - web::json::value WriteAmbientLight (FbxScene &pScene) ; + void lightAttenuation (FbxLight *pLight, Json::Value &lightDef) ; + Json::Value WriteLight (FbxNode *pNode) ; + Json::Value WriteAmbientLight (FbxScene &pScene) ; // material - utility::string_t LighthingModel (FbxSurfaceMaterial *pMaterial) ; - web::json::value WriteMaterialTransparencyParameter (const utility::char_t *pszName, FbxPropertyT &property, FbxPropertyT &propertyColor, FbxProperty &propertyOpaque, web::json::value &values, web::json::value &techniqueParameters) ; - //web::json::value WriteMaterialTransparencyParameter (const utility::char_t *pszName, FbxPropertyT &property, web::json::value &values, web::json::value &techniqueParameters) ; - web::json::value WriteMaterialParameter (const utility::char_t *pszName, FbxPropertyT &property, double factor, web::json::value &values, web::json::value &techniqueParameters) ; - web::json::value WriteMaterialParameter (const utility::char_t *pszName, FbxPropertyT &property, web::json::value &values, web::json::value &techniqueParameters) ; - web::json::value WriteMaterialParameter (const utility::char_t *pszName, FbxSurfaceMaterial *pMaterial, const char *propertyName, const char *factorName, web::json::value &values, web::json::value &techniqueParameters) ; - web::json::value WriteMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; - web::json::value WriteDefaultMaterial (FbxNode *pNode) ; - web::json::value WritePhongMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; - web::json::value WriteLambertMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; - web::json::value WriteConstantShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; - web::json::value WriteBlinnShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; - web::json::value WriteDefaultShadingModelWithCGFXMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; - web::json::value WriteDefaultShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; - web::json::value WriteDefaultShadingModelMaterial (FbxNode *pNode) ; + std::string LighthingModel (FbxSurfaceMaterial *pMaterial) ; + Json::Value WriteMaterialTransparencyParameter (const char *pszName, FbxPropertyT &property, FbxPropertyT &propertyColor, FbxProperty &propertyOpaque, Json::Value &values, Json::Value &techniqueParameters) ; + //Json::Value WriteMaterialTransparencyParameter (const char *pszName, FbxPropertyT &property, Json::Value &values, Json::Value &techniqueParameters) ; + Json::Value WriteMaterialParameter (const char *pszName, FbxPropertyT &property, double factor, Json::Value &values, Json::Value &techniqueParameters) ; + Json::Value WriteMaterialParameter (const char *pszName, FbxPropertyT &property, Json::Value &values, Json::Value &techniqueParameters) ; + Json::Value WriteMaterialParameter (const char *pszName, FbxSurfaceMaterial *pMaterial, const char *propertyName, const char *factorName, Json::Value &values, Json::Value &techniqueParameters) ; + Json::Value WriteMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; + Json::Value WriteDefaultMaterial (FbxNode *pNode) ; + Json::Value WritePhongMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; + Json::Value WriteLambertMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; + Json::Value WriteConstantShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; + Json::Value WriteBlinnShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; + Json::Value WriteDefaultShadingModelWithCGFXMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; + Json::Value WriteDefaultShadingModelMaterial (FbxNode *pNode, FbxSurfaceMaterial *pMaterial) ; + Json::Value WriteDefaultShadingModelMaterial (FbxNode *pNode) ; // mesh - web::json::value WriteMesh (FbxNode *pNode) ; + Json::Value WriteMesh (FbxNode *pNode) ; // line - //web::json::value WriteLine (FbxNode *pNode) ; + //Json::Value WriteLine (FbxNode *pNode) ; // null - web::json::value WriteNull (FbxNode *pNode) ; + Json::Value WriteNull (FbxNode *pNode) ; // program - web::json::value WriteProgram (FbxNode *pNode, FbxSurfaceMaterial *pMaterial, utility::string_t programName, web::json::value &attributes) ; + Json::Value WriteProgram (FbxNode *pNode, FbxSurfaceMaterial *pMaterial, std::string programName, Json::Value &attributes) ; // scenes / scene bool WriteScene (FbxScene *pScene, int poseIndex =-1) ; // shaders - web::json::value WriteShaders (FbxNode *pNode, web::json::value &program) ; + Json::Value WriteShaders (FbxNode *pNode, Json::Value &program) ; // technique - void AdditionalTechniqueParameters (FbxNode *pNode, web::json::value &techniqueParameters, bool bHasNormals =false) ; - void TechniqueParameters (FbxNode *pNode, web::json::value &techniqueParameters, web::json::value &attributes, web::json::value &accessors, bool bHasMaterial =true) ; - web::json::value WriteTechnique (FbxNode *pNode, FbxSurfaceMaterial *pMaterial, web::json::value &techniqueParameters) ; + void AdditionalTechniqueParameters (FbxNode *pNode, Json::Value &techniqueParameters, bool bHasNormals =false) ; + void TechniqueParameters (FbxNode *pNode, Json::Value &techniqueParameters, Json::Value &attributes, Json::Value &accessors, bool bHasMaterial =true) ; + Json::Value WriteTechnique (FbxNode *pNode, FbxSurfaceMaterial *pMaterial, Json::Value &techniqueParameters) ; // textures - web::json::value WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMaterial *pMaterial, web::json::value ¶ms) ; - web::json::value WriteTexture (FbxTexture *pTexture) ; + Json::Value WriteTextureBindings (FbxMesh *pMesh, FbxSurfaceMaterial *pMaterial, Json::Value ¶ms) ; + Json::Value WriteTexture (FbxTexture *pTexture) ; // buffer bool WriteShaders () ; private: - typedef web::json::value (gltfWriter::*ExporterRouteFct) (FbxNode *pNode) ; + typedef Json::Value (gltfWriter::*ExporterRouteFct) (FbxNode *pNode) ; typedef std::map ExporterRoutes ; static ExporterRoutes _routes ; - template - web::json::value WriteArray (std::vector &data, int size, FbxNode *pNode, const utility::char_t *suffix) ; - template - web::json::value WriteArray (FbxArray &data, FbxNode *pNode, const utility::char_t *suffix) ; - template - web::json::value WriteArray (std::vector &data, FbxNode *pNode, const utility::char_t *suffix) ; - - template - web::json::value WriteArrayWithMinMax (FbxArray &data, FbxNode *pNode, const utility::char_t *suffix) ; - template - web::json::value WriteArrayWithMinMax (std::vector &data, FbxNode *pNode, const utility::char_t *suffix) ; - template - web::json::value WriteArrayWithMinMax (FbxArray &data, T bMin, T bMax, FbxNode *pNode, const utility::char_t *suffix) ; - template - web::json::value WriteArrayWithMinMax (std::vector &data, T bMin, T bMax, FbxNode *pNode, const utility::char_t *suffix) ; + template + Json::Value WriteArray (std::vector &data, int size, FbxNode *pNode, const char *suffix) ; + template + Json::Value WriteArray (FbxArray &data, FbxNode *pNode, const char *suffix) ; + template + Json::Value WriteArray (std::vector &data, FbxNode *pNode, const char *suffix) ; + + template + Json::Value WriteArrayWithMinMax (FbxArray &data, FbxNode *pNode, const char *suffix) ; + template + Json::Value WriteArrayWithMinMax (std::vector &data, FbxNode *pNode, const char *suffix) ; + template + Json::Value WriteArrayWithMinMax (FbxArray &data, T bMin, T bMax, FbxNode *pNode, const char *suffix) ; + template + Json::Value WriteArrayWithMinMax (std::vector &data, T bMin, T bMax, FbxNode *pNode, const char *suffix) ; } ; //----------------------------------------------------------------------------- template -web::json::value gltfWriter::WriteArray (std::vector &data, int size, FbxNode *pNode, const utility::char_t *suffix) { +Json::Value gltfWriter::WriteArray (std::vector &data, int size, FbxNode *pNode, const char *suffix) { std::ofstream::pos_type offset =_bin.tellg () ; //std::copy (data.begin (), data.end (), std::ostream_iterator (_bin)) ; #if defined(_WIN32) || defined(_WIN64) @@ -203,45 +204,44 @@ web::json::value gltfWriter::WriteArray (std::vector &data, int size, FbxN _bin.write ((uint8_t *)&(*iter), sizeof (Type)) ; #endif // bufferView - web::json::value viewDef =web::json::value::object () ; - FbxString filename =FbxPathUtils::GetFileName (utility::conversions::to_utf8string (_fileName).c_str (), false) ; - viewDef [U("buffer")] =web::json::value::string (utility::conversions::to_string_t (filename.Buffer ())) ; + Json::Value viewDef( Json::objectValue ) ; + FbxString filename =FbxPathUtils::GetFileName (_fileName.c_str (), false) ; + viewDef [("buffer")] =filename.Buffer () ; size_t nb =data.size () / size ; - viewDef [U("byteLength")] =web::json::value::number ((int)(sizeof (Type) * nb * size)) ; - viewDef [U("byteOffset")] =web::json::value::number ((int)offset) ; + viewDef [("byteLength")] =((int)(sizeof (Type) * nb * size)) ; + viewDef [("byteOffset")] =((int)offset) ; // Array buffers (ARRAY_BUFFER) : These buffers contain vertex attributes, such as vertex coordinates, texture coordinate data, // per vertex - color data, and normals.They can be interleaved (using the stride parameter) or sequential, with one array after // another (write 1, 000 vertices, then 1, 000 normals, and so on).glVertexPointer and glNormalPointer each point to the appropriate offsets. // Element array buffers (ELEMENT_ARRAY_BUFFER) : This type of buffer is used mainly for the element pointer in glDraw [Range]Elements (). // It contains only indices of elements. - viewDef [U("target")] =size == 1 ? IOglTF::ELEMENT_ARRAY_BUFFER : IOglTF::ARRAY_BUFFER ; // Valid values are 34962 (ARRAY_BUFFER) or 34963 (ELEMENT_ARRAY_BUFFER) - viewDef [U("name")] =web::json::value::string (nodeId (pNode, true) + suffix + U("_Buffer")) ; - web::json::value view =web::json::value::object ({ { - nodeId (pNode, true) + suffix + U("_Buffer"), - viewDef - } }) ; + viewDef [("target")] =size == 1 ? IOglTF::ELEMENT_ARRAY_BUFFER : IOglTF::ARRAY_BUFFER ; // Valid values are 34962 (ARRAY_BUFFER) or 34963 (ELEMENT_ARRAY_BUFFER) + viewDef [("name")] =nodeId (pNode, true) + suffix + ("_Buffer") ; + Json::Value view; + view[nodeId (pNode, true) + suffix + ("_Buffer")] = viewDef ; // Accessor - web::json::value accDef =web::json::value::object () ; - accDef [U("bufferView")] =web::json::value::string (nodeId (pNode, true) + suffix + U("_Buffer")) ; - accDef [U("byteOffset")] =web::json::value::number ((int)0) ; - accDef [U("byteStride")] =web::json::value::number (/*size == 1 ? 0 :*/ (int)sizeof (Type) * size) ; - accDef [U("componentType")] =web::json::value::number ((int)IOglTF::accessorComponentType ()) ; - accDef [U("count")] =web::json::value::number ((int)nb) ; - //accDef [U("min")] =web::json::value::array ({ { (float)bMin.Buffer () [0], (float)bMin.Buffer () [1], (float)bMin.Buffer () [2] } }) ; - //accDef [U("max")] =web::json::value::array ({ { (float)bMax.Buffer () [0], (float)bMax.Buffer () [1], (float)bMax.Buffer () [2] } }) ; - accDef [U("type")] =web::json::value::string (IOglTF::accessorType (size, 1)) ; - accDef [U("name")] =web::json::value::string (nodeId (pNode, true) + suffix) ; - web::json::value acc =web::json::value::object ({ { - nodeId (pNode, true) + suffix, - accDef - } }) ; - - return (web::json::value::object ({ { U("accessors"), acc }, { U("bufferViews"), view } })) ; + Json::Value accDef ; + accDef [("bufferView")] =(nodeId (pNode, true) + suffix + ("_Buffer")) ; + accDef [("byteOffset")] =((int)0) ; + accDef [("byteStride")] =(/*size == 1 ? 0 :*/ (int)sizeof (Type) * size) ; + accDef [("componentType")] =((int)IOglTF::accessorComponentType ()) ; + accDef [("count")] =((int)nb) ; + //accDef [("min")] =Json::Value::array ({ { (float)bMin.Buffer () [0], (float)bMin.Buffer () [1], (float)bMin.Buffer () [2] } }) ; + //accDef [("max")] =Json::Value::array ({ { (float)bMax.Buffer () [0], (float)bMax.Buffer () [1], (float)bMax.Buffer () [2] } }) ; + accDef [("type")] =(IOglTF::accessorType (size, 1)) ; + accDef [("name")] =(nodeId (pNode, true) + suffix) ; + Json::Value acc; + acc[nodeId (pNode, true) + suffix] = accDef ; + + Json::Value ret; + ret["accessors"] = acc; + ret["bufferViews"] = view; + return ret ; } template -web::json::value gltfWriter::WriteArray (FbxArray &data, FbxNode *pNode, const utility::char_t *suffix) { +Json::Value gltfWriter::WriteArray (FbxArray &data, FbxNode *pNode, const char *suffix) { // glTF/Collada do not support double, convert to float (or Type) int size =sizeof (decltype(std::declval ().mData)) / sizeof (decltype(std::declval ().mData [0])) ; int nb =data.GetCount () ; @@ -254,7 +254,7 @@ web::json::value gltfWriter::WriteArray (FbxArray &data, FbxNode *pNode, cons } template -web::json::value gltfWriter::WriteArray (std::vector &data, FbxNode *pNode, const utility::char_t *suffix) { +Json::Value gltfWriter::WriteArray (std::vector &data, FbxNode *pNode, const char *suffix) { // glTF/Collada do not support double, convert to float (or Type) int size =sizeof (decltype(std::declval ().mData)) / sizeof (decltype(std::declval ().mData [0])) ; int nb =(int)data.size () ; @@ -266,7 +266,7 @@ web::json::value gltfWriter::WriteArray (std::vector &data, FbxNode *pNode, c } template -web::json::value gltfWriter::WriteArrayWithMinMax (FbxArray &data, FbxNode *pNode, const utility::char_t *suffix) { +Json::Value gltfWriter::WriteArrayWithMinMax (FbxArray &data, FbxNode *pNode, const char *suffix) { int nb =data.GetCount () ; std::vector fdata (nb) ; for ( int i =0 ; i < nb ; i++ ) @@ -275,7 +275,7 @@ web::json::value gltfWriter::WriteArrayWithMinMax (FbxArray &data, FbxNode *p } template -web::json::value gltfWriter::WriteArrayWithMinMax (std::vector &data, FbxNode *pNode, const utility::char_t *suffix) { +Json::Value gltfWriter::WriteArrayWithMinMax (std::vector &data, FbxNode *pNode, const char *suffix) { int size =sizeof (decltype(std::declval ().mData)) / sizeof (decltype(std::declval ().mData [0])) ; #pragma push_macro ("min") #undef min @@ -300,7 +300,7 @@ web::json::value gltfWriter::WriteArrayWithMinMax (std::vector &data, FbxNode } template -web::json::value gltfWriter::WriteArrayWithMinMax (FbxArray &data, T bMin, T bMax, FbxNode *pNode, const utility::char_t *suffix) { +Json::Value gltfWriter::WriteArrayWithMinMax (FbxArray &data, T bMin, T bMax, FbxNode *pNode, const char *suffix) { int nb =data.GetCount () ; std::vector fdata (nb) ; for ( int i =0 ; i < nb ; i++ ) @@ -309,19 +309,17 @@ web::json::value gltfWriter::WriteArrayWithMinMax (FbxArray &data, T bMin, T } template -web::json::value gltfWriter::WriteArrayWithMinMax (std::vector &data, T bMin, T bMax, FbxNode *pNode, const utility::char_t *suffix) { - web::json::value ret =WriteArray (data, pNode, suffix) ; - web::json::value accDef =ret [U ("accessors")] [GetJsonFirstKey (ret [U ("accessors")])] ; - //accDef [U("min")] =web::json::value::array ({ { (float)bMin.Buffer () [0], (float)bMin.Buffer () [1], (float)bMin.Buffer () [2] } }) ; - //accDef [U("max")] =web::json::value::array ({ { (float)bMax.Buffer () [0], (float)bMax.Buffer () [1], (float)bMax.Buffer () [2] } }) ; +Json::Value gltfWriter::WriteArrayWithMinMax (std::vector &data, T bMin, T bMax, FbxNode *pNode, const char *suffix) { + Json::Value ret =WriteArray (data, pNode, suffix) ; + Json::Value accDef =ret [("accessors")] [GetJsonFirstKey (ret [("accessors")])] ; + //accDef [("min")] =Json::Value::array ({ { (float)bMin.Buffer () [0], (float)bMin.Buffer () [1], (float)bMin.Buffer () [2] } }) ; + //accDef [("max")] =Json::Value::array ({ { (float)bMax.Buffer () [0], (float)bMax.Buffer () [1], (float)bMax.Buffer () [2] } }) ; int size =sizeof (decltype(std::declval ().mData)) / sizeof (decltype(std::declval ().mData [0])) ; - accDef [U ("min")] =web::json::value::array () ; for ( int j =0 ; j < size ; j++ ) - accDef [U ("min")] [j] =(Type)bMin.Buffer () [j] ; - accDef [U ("max")] =web::json::value::array () ; + accDef [("min")] [j] =(Type)bMin.Buffer () [j] ; for ( int j =0 ; j < size ; j++ ) - accDef [U ("max")] [j] =(Type)bMax.Buffer () [j] ; - ret [U ("accessors")] [GetJsonFirstKey (ret [U ("accessors")])] =accDef ; + accDef [("max")] [j] =(Type)bMax.Buffer () [j] ; + ret [("accessors")] [GetJsonFirstKey (ret [("accessors")])] =accDef ; return (ret) ; } diff --git a/IO-glTF/gltfWriterVBO.cpp b/IO-glTF/gltfWriterVBO.cpp index c60291c..99d4687 100644 --- a/IO-glTF/gltfWriterVBO.cpp +++ b/IO-glTF/gltfWriterVBO.cpp @@ -184,8 +184,8 @@ void gltfwriterVBO::GetLayerElements (bool bInGeometry /*=true*/) { // FbxLayerElement::EType channel =static_cast(index) ; // FbxLayerElementUV *pLayerElementUVs =elementUVs (channel, -1) ; // if ( pLayerElementUVs ) { - // utility::string_t st (U("TEXCOORD_0")) ; - // utility::string_t key =utility::conversions::to_string_t (FbxLayerElement::sTextureChannelNames [channel - FbxLayerElement::sTypeTextureStartIndex]) ; + // std::string st (("TEXCOORD_0")) ; + // std::string key =utility::conversions::to_string_t (FbxLayerElement::sTextureChannelNames [channel - FbxLayerElement::sTypeTextureStartIndex]) ; // _uvSets [key] =st ; // } //} @@ -202,13 +202,11 @@ void gltfwriterVBO::GetLayerElements (bool bInGeometry /*=true*/) { FbxLayerElementUV *pLayerElementUVs =elementUVs (channel, iLayer) ; channels [channel] =pLayerElementUVs ; if ( pLayerElementUVs ) { - utility::string_t st (U("TEXCOORD_")) ; + std::string st (("TEXCOORD_")) ; st +=utility::conversions::to_string_t ((int)_uvSets.size ()) ; //FbxString name =pLayerElementUVs->GetName () ; // uvSet //_uvSets [name == "" ? "default" : name] =utility::conversions::to_string_t (st.Buffer ()) ; - utility::string_t key =utility::conversions::to_string_t ( - FbxLayerElement::sTextureChannelNames [channel - FbxLayerElement::sTypeTextureStartIndex] - ) ; + std::string key = FbxLayerElement::sTextureChannelNames [channel - FbxLayerElement::sTypeTextureStartIndex] ; _uvSets [key] =st ; } } @@ -525,8 +523,8 @@ void gltfwriterVBOT::GetLayerElements (bool bInGeometry /*=true*/) { // FbxLayerElement::EType channel =static_cast(index) ; // FbxLayerElementUV *pLayerElementUVs =elementUVs (channel, -1) ; // if ( pLayerElementUVs ) { - // utility::string_t st (U("TEXCOORD_0")) ; - // utility::string_t key =utility::conversions::to_string_t (FbxLayerElement::sTextureChannelNames [channel - FbxLayerElement::sTypeTextureStartIndex]) ; + // std::string st (("TEXCOORD_0")) ; + // std::string key =utility::conversions::to_string_t (FbxLayerElement::sTextureChannelNames [channel - FbxLayerElement::sTypeTextureStartIndex]) ; // _uvSets [key] =st ; // } //} @@ -543,11 +541,11 @@ void gltfwriterVBOT::GetLayerElements (bool bInGeometry /*=true*/) { FbxLayerElementUV *pLayerElementUVs =elementUVs (channel, iLayer) ; channels [channel] =pLayerElementUVs ; if ( pLayerElementUVs ) { - utility::string_t st (U("TEXCOORD_")) ; + std::string st (("TEXCOORD_")) ; st +=utility::conversions::to_string_t ((int)_uvSets.size ()) ; //FbxString name =pLayerElementUVs->GetName () ; // uvSet //_uvSets [name == "" ? "default" : name] =utility::conversions::to_string_t (st.Buffer ()) ; - utility::string_t key =utility::conversions::to_string_t ( + std::string key =utility::conversions::to_string_t ( FbxLayerElement::sTextureChannelNames [channel - FbxLayerElement::sTypeTextureStartIndex] ) ; _uvSets [key] =st ; diff --git a/IO-glTF/gltfwriterVBO.h b/IO-glTF/gltfwriterVBO.h index 6e5f225..3de2969 100644 --- a/IO-glTF/gltfwriterVBO.h +++ b/IO-glTF/gltfwriterVBO.h @@ -54,7 +54,7 @@ class gltfwriterVBO { std::vector _in_tangents, _out_tangents ; std::vector _in_binormals, _out_binormals ; std::vector _in_vcolors, _out_vcolors ; - std::map _uvSets ; + std::map _uvSets ; FbxMesh *_pMesh ; public: @@ -72,7 +72,7 @@ class gltfwriterVBO { std::vector getTangents () { return (_out_tangents) ; } std::vector getBinormals () { return (_out_binormals) ; } std::vector getVertexColors () { return (_out_vcolors) ; } - std::map getUvSets () { return (_uvSets) ; } + std::map getUvSets () { return (_uvSets) ; } protected: FbxLayerElementNormal *elementNormals (int iLayer =-1) ; @@ -106,7 +106,7 @@ class gltfwriterVBOT { std::vector _in_tangents, _out_tangents ; std::vector _in_binormals, _out_binormals ; std::vector _in_vcolors, _out_vcolors ; - std::map _uvSets ; + std::map _uvSets ; T *_pMesh ; public: @@ -124,7 +124,7 @@ class gltfwriterVBOT { std::vector getTangents () { return (_out_tangents) ; } std::vector getBinormals () { return (_out_binormals) ; } std::vector getVertexColors () { return (_out_vcolors) ; } - std::map getUvSets () { return (_uvSets) ; } + std::map getUvSets () { return (_uvSets) ; } protected: FbxLayerElementNormal *elementNormals (int iLayer =-1) ; diff --git a/IO-glTF/string_t_utils.h b/IO-glTF/string_t_utils.h index b69a746..24305b2 100644 --- a/IO-glTF/string_t_utils.h +++ b/IO-glTF/string_t_utils.h @@ -23,7 +23,7 @@ namespace utility { namespace conversions { -inline utility::string_t to_string_t (int val) { +inline std::string to_string_t (int val) { #ifdef _UTF16_STRINGS return (std::to_wstring (val)) ; #else @@ -35,12 +35,12 @@ inline utility::string_t to_string_t (int val) { namespace details { -inline int limitedCompareTo (const utility::string_t &a, const utility::string_t &b) { +inline int limitedCompareTo (const std::string &a, const std::string &b) { return (a.compare (0, b.size (), b)) ; } -inline int limitedCompareTo (const utility::string_t &a, const utility::char_t *b) { - return (a.compare (0, utility::string_t (b).size (), utility::string_t (b))) ; +inline int limitedCompareTo (const std::string &a, const char *b) { + return (a.compare (0, std::string (b).size (), std::string (b))) ; } } diff --git a/glTF/CMakeLists.txt b/glTF/CMakeLists.txt index 267ad70..14e8e5b 100644 --- a/glTF/CMakeLists.txt +++ b/glTF/CMakeLists.txt @@ -7,6 +7,7 @@ set (GLTF_VERSION ${GLTF_MAJOR_VERSION}.${GLTF_MINOR_VERSION}.${GLTF_PATCH_VERSI # glTF executable file (GLOB_RECURSE glTF-src ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) include_directories ( + ../ ${FBX_SDK_INCLUDES} /usr/local/include ../IO-glTF @@ -18,8 +19,8 @@ link_directories ( add_executable (glTF ${glTF-src}) target_link_libraries ( glTF + jsoncpp ${FBX_SDK_LIBRARY} - ${CASABLANCA_LIBRARY} - ${Boost_LIBRARIES} ${Boost_FRAMEWORK} + dl ) diff --git a/glTF/StdAfx.h b/glTF/StdAfx.h index d34242b..6d6c5de 100644 --- a/glTF/StdAfx.h +++ b/glTF/StdAfx.h @@ -36,10 +36,8 @@ // C++ REST SDK (codename "Casablanca") // https://casablanca.codeplex.com/ -#include -#include -typedef web::json::value JsonValue ; -typedef web::json::value::value_type JsonValueType ; +#include "jsoncpp/json-forwards.h" +typedef Json::Value JsonValue ; // C++ FBX SDK // http://www.autodeks.com/developfbx diff --git a/glTF/getopt.cpp b/glTF/getopt.cpp index 3a32d8c..18dd00e 100644 --- a/glTF/getopt.cpp +++ b/glTF/getopt.cpp @@ -47,6 +47,7 @@ EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. #include #ifdef __APPLE__ #include +typedef int errno_t ; #else #include #endif diff --git a/glTF/glTF.cpp b/glTF/glTF.cpp index f159e52..c394b79 100644 --- a/glTF/glTF.cpp +++ b/glTF/glTF.cpp @@ -20,6 +20,7 @@ // #include "StdAfx.h" #include "getopt.h" +#include #if defined(_WIN32) || defined(_WIN64) #include "tchar.h" #endif @@ -32,38 +33,38 @@ // -f $(ProjectDir)\..\models\monster\monster.fbx -o $(ProjectDir)\..\models\monster\out -n test -c // -f $(ProjectDir)\..\models\Carnivorous_plant\Carnivorous_plant.fbx -o $(ProjectDir)\..\models\Carnivorous_plant\out -n test -c - //{ U("n"), U("a"), required_argument, U("-a -> export animations, argument [bool], default:true") }, - //{ U("n"), U("g"), required_argument, U("-g -> [experimental] GLSL version to output in generated shaders") }, - //{ U("n"), U("d"), no_argument, U("-d -> export pass details to be able to regenerate shaders and states") }, - //{ U("n"), U("c"), required_argument, U("-c -> compression type: available: Open3DGC [string]") }, - //{ U("n"), U("m"), required_argument, U("-m -> compression mode: for Open3DGC can be \"ascii\"(default) or \"binary\" [string]") }, - //{ U("n"), U("n"), no_argument, U("-n -> don't combine animations with the same target") } + //{ ("n"), ("a"), required_argument, ("-a -> export animations, argument [bool], default:true") }, + //{ ("n"), ("g"), required_argument, ("-g -> [experimental] GLSL version to output in generated shaders") }, + //{ ("n"), ("d"), no_argument, ("-d -> export pass details to be able to regenerate shaders and states") }, + //{ ("n"), ("c"), required_argument, ("-c -> compression type: available: Open3DGC [string]") }, + //{ ("n"), ("m"), required_argument, ("-m -> compression mode: for Open3DGC can be \"ascii\"(default) or \"binary\" [string]") }, + //{ ("n"), ("n"), no_argument, ("-n -> don't combine animations with the same target") } void usage () { - ucout << std::endl << U("glTF [-h] [-v] [-n] [-d] [-t] [-l] [-c] [-e] [-o ] -f ") << std::endl ; - ucout << U("-f/--file \t\t- file to convert to glTF [string]") << std::endl ; - ucout << U("-o/--output \t\t- path of output directory [string]") << std::endl ; - ucout << U("-n/--name \t\t- override the scene name [string]") << std::endl ; - ucout << U("-d/--degree \t\t- output angles in degrees vs radians (default to radians)") << std::endl ; - ucout << U("-t/--transparency \t- invert transparency") << std::endl ; - //ucout << U("-l/--lighting \t- enable default lighting (if no lights in scene)") << std::endl ; - ucout << U("-c/--copy \t\t- copy all media to the target directory (cannot be combined with --embed)") << std::endl ; - ucout << U("-e/--embed \t\t- embed all resources as Data URIs (cannot be combined with --copy)") << std::endl ; - ucout << U("-h/--help \t\t- this message") << std::endl ; - ucout << U("-v/--version \t\t- version") << std::endl ; + std::cout << std::endl << ("glTF [-h] [-v] [-n] [-d] [-t] [-l] [-c] [-e] [-o ] -f ") << std::endl ; + std::cout << ("-f/--file \t\t- file to convert to glTF [string]") << std::endl ; + std::cout << ("-o/--output \t\t- path of output directory [string]") << std::endl ; + std::cout << ("-n/--name \t\t- override the scene name [string]") << std::endl ; + std::cout << ("-d/--degree \t\t- output angles in degrees vs radians (default to radians)") << std::endl ; + std::cout << ("-t/--transparency \t- invert transparency") << std::endl ; + //std::cout << ("-l/--lighting \t- enable default lighting (if no lights in scene)") << std::endl ; + std::cout << ("-c/--copy \t\t- copy all media to the target directory (cannot be combined with --embed)") << std::endl ; + std::cout << ("-e/--embed \t\t- embed all resources as Data URIs (cannot be combined with --copy)") << std::endl ; + std::cout << ("-h/--help \t\t- this message") << std::endl ; + std::cout << ("-v/--version \t\t- version") << std::endl ; } static struct option long_options [] ={ - { U("file"), ARG_REQ, 0, U('f') }, - { U("output"), ARG_REQ, 0, U('o') }, - { U("name"), ARG_REQ, 0, U('n') }, - { U("degree"), ARG_NONE, 0, U('d') }, - { U("transparency"), ARG_NONE, 0, U('t') }, - { U("lighting"), ARG_NONE, 0, U('l') }, - { U("copy"), ARG_NONE, 0, U('c') }, - { U("embed"), ARG_NONE, 0, U('e') }, - { U("help"), ARG_NONE, 0, U('h') }, - { U("version"), ARG_NONE, 0, U('v') }, + { ("file"), ARG_REQ, 0, ('f') }, + { ("output"), ARG_REQ, 0, ('o') }, + { ("name"), ARG_REQ, 0, ('n') }, + { ("degree"), ARG_NONE, 0, ('d') }, + { ("transparency"), ARG_NONE, 0, ('t') }, + { ("lighting"), ARG_NONE, 0, ('l') }, + { ("copy"), ARG_NONE, 0, ('c') }, + { ("embed"), ARG_NONE, 0, ('e') }, + { ("help"), ARG_NONE, 0, ('h') }, + { ("version"), ARG_NONE, 0, ('v') }, { ARG_NULL, ARG_NULL, ARG_NULL, ARG_NULL } } ; @@ -74,9 +75,9 @@ int _tmain (int argc, _TCHAR *argv []) { int main (int argc, char *argv []) { #endif bool bLoop =true ; - utility::string_t inFile ; - utility::string_t outDir ; - utility::string_t name ; + std::string inFile ; + std::string outDir ; + std::string name ; bool angleInDegree =false ; bool reverseTransparency =false ; bool defaultLighting =false ; @@ -87,7 +88,7 @@ int main (int argc, char *argv []) { // http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html // http://www.gnu.org/software/libc/manual/html_node/Argp-Examples.html#Argp-Examples // http://stackoverflow.com/questions/13251732/c-how-to-specify-an-optstring-in-the-getopt-function - int c =getopt_long (argc, argv, U ("f:o:n:tlcehv"), long_options, &option_index) ; + int c =getopt_long (argc, argv, ("f:o:n:tlcehv"), long_options, &option_index) ; // Check for end of operation or error if ( c == -1 ) break ; @@ -96,41 +97,41 @@ int main (int argc, char *argv []) { switch ( c ) { case 0: break ; - case U('?'): + case ('?'): // getopt_long already printed an error message. break ; - case U(':'): // missing option argument - ucout << U("option \'") << optopt << U("\' requires an argument") << std::endl ; + case (':'): // missing option argument + std::cout << ("option \'") << optopt << ("\' requires an argument") << std::endl ; break ; default: bLoop =false ; break ; - case U('h'): // help message + case ('h'): // help message usage () ; return (0) ; - case U('f'): // file to convert to glTF [string] + case ('f'): // file to convert to glTF [string] inFile =optarg ; break ; - case U('o'): // path of output directory argument [string] + case ('o'): // path of output directory argument [string] outDir =optarg ; break ; - case U('n'): // override the scene name [string] + case ('n'): // override the scene name [string] name =optarg ; break ; - case U('d'): // invert transparency + case ('d'): // invert transparency angleInDegree =true ; break ; - case U('t'): // invert transparency + case ('t'): // invert transparency reverseTransparency =true ; break ; - case U('l'): // enable default lighting (if no lights in scene) + case ('l'): // enable default lighting (if no lights in scene) defaultLighting =true ; break ; - case U('c'): // copy all media to the target directory (cannot be combined with --embed) + case ('c'): // copy all media to the target directory (cannot be combined with --embed) copyMedia =!embedMedia ; break ; - case U('e'): // embed all resources as Data URIs (cannot be combined with --copy) + case ('e'): // embed all resources as Data URIs (cannot be combined with --copy) embedMedia =!copyMedia ; break ; } @@ -139,27 +140,27 @@ int main (int argc, char *argv []) { if ( inFile.length () == 0 || _taccess_s (inFile.c_str (), 0) == ENOENT ) return (-1) ; #else - if ( inFile.length () == 0 || access (inFile.c_str (), 0) == ENOENT ) - return (-1) ; +// if ( inFile.length () == 0 || access (inFile.c_str (), 0) == ENOENT ) +// return (-1) ; #endif if ( outDir.length () == 0 ) - outDir =utility::conversions::to_string_t (FbxPathUtils::GetFolderName (utility::conversions::to_utf8string (inFile).c_str ()).Buffer ()) ; + outDir = (FbxPathUtils::GetFolderName ( (inFile).c_str ()).Buffer ()) ; #if defined(_WIN32) || defined(_WIN64) - if ( outDir [outDir.length () - 1] != U('\\') ) - outDir +=U('\\') ; + if ( outDir [outDir.length () - 1] != ('\\') ) + outDir +=('\\') ; #else - if ( outDir [outDir.length () - 1] != U('/') ) - outDir +=U('/') ; + if ( outDir [outDir.length () - 1] != ('/') ) + outDir +=('/') ; #endif std::shared_ptr asset (new gltfPackage ()) ; asset->ioSettings (name.c_str (), angleInDegree, reverseTransparency, defaultLighting, copyMedia, embedMedia) ; - ucout << U("Loading file: ") << inFile << U("...") << std::endl ; + std::cout << ("Loading file: ") << inFile << ("...") << std::endl ; bool bRet =asset->load (inFile) ; - ucout << U("Converting to GLTF ...") << std::endl ; + std::cout << ("Converting to GLTF ...") << std::endl ; bRet =asset->save (outDir) ; - ucout << U("done!") << std::endl ; + std::cout << ("done!") << std::endl ; return (0) ; } diff --git a/glTF/gltfPackage.cpp b/glTF/gltfPackage.cpp index 6349a4a..506f158 100644 --- a/glTF/gltfPackage.cpp +++ b/glTF/gltfPackage.cpp @@ -21,12 +21,13 @@ #include "StdAfx.h" #include "glTF.h" #include "gltfPackage.h" +#include //----------------------------------------------------------------------------- /*static*/ FbxAutoPtr fbxSdkMgr::_singleton ; fbxSdkMgr::fbxSdkMgr () : _sdkManager(FbxManager::Create ()) { - _ASSERTE( _sdkManager ) ; + assert( _sdkManager ) ; FbxIOSettings *pIOSettings =FbxIOSettings::Create (_sdkManager, IOSROOT) ; //pIOSettings->SetBoolProp (IMP_FBX_CONSTRAINT, true) ; //pIOSettings->SetBoolProp (IMP_FBX_CONSTRAINT_COUNT, true) ; @@ -64,19 +65,19 @@ fbxSdkMgr::~fbxSdkMgr () { } FbxSharedDestroyPtr &fbxSdkMgr::fbxMgr () { - _ASSERTE( _sdkManager ) ; + assert( _sdkManager ) ; return (_sdkManager) ; } //----------------------------------------------------------------------------- -gltfPackage::gltfPackage () : _scene(nullptr), _ioSettings ({ U("") }) { +gltfPackage::gltfPackage () : _scene(nullptr), _ioSettings ({ ("") }) { } gltfPackage::~gltfPackage () { } void gltfPackage::ioSettings ( - const utility::char_t *name /*=nullptr*/, + const char *name /*=nullptr*/, bool angleInDegree /*=false*/, bool invertTransparency /*=false*/, bool defaultLighting /*=false*/, @@ -84,7 +85,7 @@ void gltfPackage::ioSettings ( bool embedMedia /*=false*/ ) { FbxIOSettings *pIOSettings =fbxSdkMgr::Instance ()->fbxMgr ()->GetIOSettings () ; - _ioSettings._name =name == nullptr ? U("") : name ; + _ioSettings._name =name == nullptr ? ("") : name ; pIOSettings->SetBoolProp (IOSN_FBX_GLTF_ANGLEINDEGREE, angleInDegree) ; pIOSettings->SetBoolProp (IOSN_FBX_GLTF_INVERTTRANSPARENCY, invertTransparency) ; pIOSettings->SetBoolProp (IOSN_FBX_GLTF_DEFAULTLIGHTING, defaultLighting) ; @@ -93,36 +94,36 @@ void gltfPackage::ioSettings ( //fbxSdkMgr::Instance ()->fbxMgr ()->SetIOSettings (pIOSettings) ; } -bool gltfPackage::load (const utility::string_t &fn) { - _ASSERTE( !_scene ) ; +bool gltfPackage::load (const std::string &fn) { + assert( !_scene ) ; auto pMgr =fbxSdkMgr::Instance ()->fbxMgr () ; - _scene.Reset (FbxScene::Create (pMgr, utility::conversions::to_utf8string (gltfPackage::filename (fn)).c_str ())) ; - _ASSERTE( !!_scene ) ; + _scene.Reset (FbxScene::Create (pMgr, (gltfPackage::filename (fn)).c_str ())) ; + assert( !!_scene ) ; bool bRet =LoadScene (fn) ; return (bRet) ; } -bool gltfPackage::import (const utility::string_t &fn) { - _ASSERTE( !_scene ) ; +bool gltfPackage::import (const std::string &fn) { + assert( !_scene ) ; auto pMgr =fbxSdkMgr::Instance ()->fbxMgr () ; - _scene.Reset (FbxScene::Create (pMgr, utility::conversions::to_utf8string (gltfPackage::filename (fn)).c_str ())) ; - _ASSERTE( !!_scene ) ; + _scene.Reset (FbxScene::Create (pMgr, (gltfPackage::filename (fn)).c_str ())) ; + assert( !!_scene ) ; bool bRet =LoadScene (fn) ; return (bRet) ; } -bool gltfPackage::save (const utility::string_t &outdir) { - _ASSERTE( !!_scene ) ; +bool gltfPackage::save (const std::string &outdir) { + assert( !!_scene ) ; bool bRet =WriteScene (outdir) ; return (bRet) ; } -/*static*/ utility::string_t gltfPackage::filename (const utility::string_t &path) { - utility::string_t filename ; - size_t pos =path.find_last_of (U("/\\")) ; - if ( pos != utility::string_t::npos ) { - size_t pos2 =path.find (U("."), pos) ; - if ( pos2 != utility::string_t::npos ) +/*static*/ std::string gltfPackage::filename (const std::string &path) { + std::string filename ; + size_t pos =path.find_last_of (("/\\")) ; + if ( pos != std::string::npos ) { + size_t pos2 =path.find (("."), pos) ; + if ( pos2 != std::string::npos ) filename.assign (path.begin () + pos + 1, path.begin () + pos2) ; else filename.assign (path.begin () + pos + 1, path.end ()) ; @@ -132,21 +133,21 @@ bool gltfPackage::save (const utility::string_t &outdir) { return (filename) ; } -/*static*/ utility::string_t gltfPackage::pathname (const utility::string_t &filename) { - utility::string_t path ; - size_t pos =filename.find_last_of (U ("/\\")) ; - if ( pos != utility::string_t::npos ) +/*static*/ std::string gltfPackage::pathname (const std::string &filename) { + std::string path ; + size_t pos =filename.find_last_of (("/\\")) ; + if ( pos != std::string::npos ) path.assign (filename.begin (), filename.begin () + pos + 1) ; else - path =U("") ; + path =("") ; return (path) ; } -bool gltfPackage::LoadScene (const utility::string_t &fn) { +bool gltfPackage::LoadScene (const std::string &fn) { auto pMgr =fbxSdkMgr::Instance ()->fbxMgr () ; FbxAutoDestroyPtr pImporter (FbxImporter::Create (pMgr, "")) ; - if ( !pImporter->Initialize (utility::conversions::to_utf8string (fn).c_str (), -1, pMgr->GetIOSettings ()) ) + if ( !pImporter->Initialize ((fn).c_str (), -1, pMgr->GetIOSettings ()) ) return (false) ; if ( pImporter->IsFBX () ) { // From this point, it is possible to access animation stack information without @@ -157,10 +158,10 @@ bool gltfPackage::LoadScene (const utility::string_t &fn) { bool bStatus =pImporter->Import (_scene) ; if ( _ioSettings._name.length () ) - _scene->SetName (utility::conversions::to_utf8string (_ioSettings._name).c_str ()) ; + _scene->SetName ((_ioSettings._name).c_str ()) ; else if ( _scene->GetName () == FbxString ("") ) //_scene->SetName ("untitled") ; - _scene->SetName (utility::conversions::to_utf8string (gltfPackage::filename (fn)).c_str ()) ; + _scene->SetName ((gltfPackage::filename (fn)).c_str ()) ; //if ( bStatus == false && pImporter->GetStatus ().GetCode () == FbxStatus::ePasswordError ) { //} @@ -236,16 +237,16 @@ bool gltfPackage::LoadScene (const utility::string_t &fn) { // return (pAffectedNodes) ; //} -bool gltfPackage::WriteScene (const utility::string_t &outdir) { +bool gltfPackage::WriteScene (const std::string &outdir) { auto pMgr =fbxSdkMgr::Instance ()->fbxMgr () ; int iFormat =pMgr->GetIOPluginRegistry ()->FindWriterIDByExtension ("gltf") ; if ( iFormat == -1 ) return (false) ; FbxAutoDestroyPtr pExporter (FbxExporter::Create (pMgr, "")) ; - utility::string_t newFn =outdir + utility::conversions::to_string_t (_scene->GetName ()) + U(".gltf") ; + std::string newFn =outdir + (_scene->GetName ()) + (".gltf") ; - bool bRet =pExporter->Initialize (utility::conversions::to_utf8string (newFn).c_str (), iFormat, pMgr->GetIOSettings ()) ; - _ASSERTE( bRet ) ; + bool bRet =pExporter->Initialize ((newFn).c_str (), iFormat, pMgr->GetIOSettings ()) ; + assert( bRet ) ; if ( !bRet ) return (false) ; diff --git a/glTF/gltfPackage.h b/glTF/gltfPackage.h index 9646bf3..9179cb9 100644 --- a/glTF/gltfPackage.h +++ b/glTF/gltfPackage.h @@ -21,6 +21,7 @@ #pragma once #include +#include //#include "webgl-idl.h" //----------------------------------------------------------------------------- @@ -44,7 +45,7 @@ class fbxSdkMgr { class gltfPackage { protected: struct IOSettings { - utility::string_t _name ; + std::string _name ; } _ioSettings ; protected: @@ -55,7 +56,7 @@ class gltfPackage { virtual ~gltfPackage () ; void ioSettings ( - const utility::char_t *name =nullptr, + const char *name =nullptr, bool angleInDegree =false, bool reverseTransparency =false, bool defaultLighting =false, @@ -63,16 +64,16 @@ class gltfPackage { bool embedMedia =false ) ; - bool load (const utility::string_t &fn) ; - bool import (const utility::string_t &fn) ; + bool load (const std::string &fn) ; + bool import (const std::string &fn) ; - bool save (const utility::string_t &outdir) ; + bool save (const std::string &outdir) ; - static utility::string_t filename (const utility::string_t &path) ; - static utility::string_t pathname (const utility::string_t &filename) ; + static std::string filename (const std::string &path) ; + static std::string pathname (const std::string &filename) ; protected: - bool LoadScene (const utility::string_t &fn) ; - bool WriteScene (const utility::string_t &outdir) ; + bool LoadScene (const std::string &fn) ; + bool WriteScene (const std::string &outdir) ; } ; diff --git a/jsoncpp/CMakeLists.txt b/jsoncpp/CMakeLists.txt new file mode 100644 index 0000000..c1187f4 --- /dev/null +++ b/jsoncpp/CMakeLists.txt @@ -0,0 +1,18 @@ +set (IOGLTF_MAJOR_VERSION 1) +set (IOGLTF_MINOR_VERSION 0) +set (IOGLTF_PATCH_VERSION 0) +set (IOGLTF_VERSION ${IOGLTF_MAJOR_VERSION}.${IOGLTF_MINOR_VERSION}.${IOGLTF_PATCH_VERSION}) + +# jsoncpp dynamic libray +file (GLOB_RECURSE jsoncpp-src ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +include_directories ( + ../ + /usr/local/include +) +link_directories ( + /usr/local/lib +) +add_library (jsoncpp SHARED ${jsoncpp-src}) +target_link_libraries ( + jsoncpp +) \ No newline at end of file diff --git a/jsoncpp/json-forwards.h b/jsoncpp/json-forwards.h new file mode 100644 index 0000000..fd21c05 --- /dev/null +++ b/jsoncpp/json-forwards.h @@ -0,0 +1,264 @@ +/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include +/// This header provides forward declaration for all JsonCpp types. + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED +# define JSON_FORWARD_AMALGATED_H_INCLUDED +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 +/// If defined, indicates that Json specific container should be used +/// (hash table & simple deque container with customizable allocator). +/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 +//# define JSON_VALUE_USE_INTERNAL_MAP 1 +/// Force usage of standard new/malloc based allocator instead of memory pool +/// based allocator. +/// The memory pools allocator used optimization (initializing Value and +/// ValueInternalLink +/// as if it was a POD) that may cause some validation tool to report errors. +/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. +//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; +#ifdef JSON_VALUE_USE_INTERNAL_MAP +class ValueMapAllocator; +class ValueInternalLink; +class ValueInternalArray; +class ValueInternalMap; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED diff --git a/jsoncpp/json.h b/jsoncpp/json.h new file mode 100644 index 0000000..7d9b6f2 --- /dev/null +++ b/jsoncpp/json.h @@ -0,0 +1,2060 @@ +/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_AMALGATED_H_INCLUDED +# define JSON_AMALGATED_H_INCLUDED +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + +// DO NOT EDIT. This file is generated by CMake from "version" +// and "version.h.in" files. +// Run CMake configure step to update it. +#ifndef JSON_VERSION_H_INCLUDED +# define JSON_VERSION_H_INCLUDED + +# define JSONCPP_VERSION_STRING "1.3.0" +# define JSONCPP_VERSION_MAJOR 1 +# define JSONCPP_VERSION_MINOR 3 +# define JSONCPP_VERSION_PATCH 0 +# define JSONCPP_VERSION_QUALIFIER +# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) + +#endif // JSON_VERSION_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 +/// If defined, indicates that Json specific container should be used +/// (hash table & simple deque container with customizable allocator). +/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 +//# define JSON_VALUE_USE_INTERNAL_MAP 1 +/// Force usage of standard new/malloc based allocator instead of memory pool +/// based allocator. +/// The memory pools allocator used optimization (initializing Value and +/// ValueInternalLink +/// as if it was a POD) that may cause some validation tool to report errors. +/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. +//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; +#ifdef JSON_VALUE_USE_INTERNAL_MAP +class ValueMapAllocator; +class ValueInternalLink; +class ValueInternalArray; +class ValueInternalMap; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_FEATURES_H_INCLUDED +#define CPPTL_JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +/** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ +class JSON_API Features { +public: + /** \brief A configuration that allows all features and assumes all strings + * are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON + * specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_; + + /// \c true if root must be either an array or an object value. Default: \c + /// false. + bool strictRoot_; + + /// \c true if dropped null placeholders are allowed. Default: \c false. + bool allowDroppedNullPlaceholders_; + + /// \c true if numeric object key are allowed. Default: \c false. + bool allowNumericKeys_; +}; + +} // namespace Json + +#endif // CPPTL_JSON_FEATURES_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_H_INCLUDED +#define CPPTL_JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include + +#ifndef JSON_USE_CPPTL_SMALLMAP +#include +#else +#include +#endif +#ifdef JSON_USE_CPPTL +#include +#endif + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + +/** \brief Type of the value held by a Value object. + */ +enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). +}; + +enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for + /// root value) + numberOfCommentPlacement +}; + +//# ifdef JSON_USE_CPPTL +// typedef CppTL::AnyEnumerator EnumMemberNames; +// typedef CppTL::AnyEnumerator EnumValues; +//# endif + +/** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignement takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ +class JSON_API StaticString { +public: + explicit StaticString(const char* czstring) : str_(czstring) {} + + operator const char*() const { return str_; } + + const char* c_str() const { return str_; } + +private: + const char* str_; +}; + +/** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * values of an #objectValue or #arrayValue can be accessed using operator[]() + *methods. + * Non const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resize and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtanis default value in the case the + *required element + * does not exist. + * + * It is possible to iterate over the list of a #objectValue values using + * the getMemberNames() method. + */ +class JSON_API Value { + friend class ValueIteratorBase; +#ifdef JSON_VALUE_USE_INTERNAL_MAP + friend class ValueInternalLink; + friend class ValueInternalMap; +#endif +public: + typedef std::vector Members; + typedef ValueIterator iterator; + typedef ValueConstIterator const_iterator; + typedef Json::UInt UInt; + typedef Json::Int Int; +#if defined(JSON_HAS_INT64) + typedef Json::UInt64 UInt64; + typedef Json::Int64 Int64; +#endif // defined(JSON_HAS_INT64) + typedef Json::LargestInt LargestInt; + typedef Json::LargestUInt LargestUInt; + typedef Json::ArrayIndex ArrayIndex; + + static const Value& null; + /// Minimum signed integer value that can be stored in a Json::Value. + static const LargestInt minLargestInt; + /// Maximum signed integer value that can be stored in a Json::Value. + static const LargestInt maxLargestInt; + /// Maximum unsigned integer value that can be stored in a Json::Value. + static const LargestUInt maxLargestUInt; + + /// Minimum signed int value that can be stored in a Json::Value. + static const Int minInt; + /// Maximum signed int value that can be stored in a Json::Value. + static const Int maxInt; + /// Maximum unsigned int value that can be stored in a Json::Value. + static const UInt maxUInt; + +#if defined(JSON_HAS_INT64) + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 minInt64; + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 maxInt64; + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static const UInt64 maxUInt64; +#endif // defined(JSON_HAS_INT64) + +private: +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION +#ifndef JSON_VALUE_USE_INTERNAL_MAP + class CZString { + public: + enum DuplicationPolicy { + noDuplication = 0, + duplicate, + duplicateOnCopy + }; + CZString(ArrayIndex index); + CZString(const char* cstr, DuplicationPolicy allocate); + CZString(const CZString& other); + ~CZString(); + CZString& operator=(CZString other); + bool operator<(const CZString& other) const; + bool operator==(const CZString& other) const; + ArrayIndex index() const; + const char* c_str() const; + bool isStaticString() const; + + private: + void swap(CZString& other); + const char* cstr_; + ArrayIndex index_; + }; + +public: +#ifndef JSON_USE_CPPTL_SMALLMAP + typedef std::map ObjectValues; +#else + typedef CppTL::SmallMap ObjectValues; +#endif // ifndef JSON_USE_CPPTL_SMALLMAP +#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +public: + /** \brief Create a default Value of the given type. + + This is a very useful constructor. + To create an empty array, pass arrayValue. + To create an empty object, pass objectValue. + Another Value can then be set to this one by assignment. +This is useful since clear() and resize() will not alter types. + + Examples: +\code +Json::Value null_value; // null +Json::Value arr_value(Json::arrayValue); // [] +Json::Value obj_value(Json::objectValue); // {} +\endcode + */ + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); +#if defined(JSON_HAS_INT64) + Value(Int64 value); + Value(UInt64 value); +#endif // if defined(JSON_HAS_INT64) + Value(double value); + Value(const char* value); + Value(const char* beginValue, const char* endValue); + /** \brief Constructs a value from a static string. + + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to this + * constructor. + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * \endcode + */ + Value(const StaticString& value); + Value(const std::string& value); +#ifdef JSON_USE_CPPTL + Value(const CppTL::ConstString& value); +#endif + Value(bool value); + /// Deep copy. + Value(const Value& other); + ~Value(); + + // Deep copy, then swap(other). + Value& operator=(Value other); + /// Swap everything. + void swap(Value& other); + /// Swap values but leave comments and source offsets in place. + void swapPayload(Value& other); + + ValueType type() const; + + /// Compare payload only, not comments etc. + bool operator<(const Value& other) const; + bool operator<=(const Value& other) const; + bool operator>=(const Value& other) const; + bool operator>(const Value& other) const; + bool operator==(const Value& other) const; + bool operator!=(const Value& other) const; + int compare(const Value& other) const; + + const char* asCString() const; + std::string asString() const; +#ifdef JSON_USE_CPPTL + CppTL::ConstString asConstString() const; +#endif + Int asInt() const; + UInt asUInt() const; +#if defined(JSON_HAS_INT64) + Int64 asInt64() const; + UInt64 asUInt64() const; +#endif // if defined(JSON_HAS_INT64) + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isUInt() const; + bool isUInt64() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return isNull() + bool operator!() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to size elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(ArrayIndex size); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](ArrayIndex index); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](int index); + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](ArrayIndex index) const; + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](int index) const; + + /// If the array contains at least index+1 elements, returns the element + /// value, + /// otherwise returns defaultValue. + Value get(ArrayIndex index, const Value& defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(ArrayIndex index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value& append(const Value& value); + + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const char* key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const char* key) const; + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const std::string& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const std::string& key) const; + /** \brief Access an object value by name, create a null member if it does not + exist. + + * If the object as no entry for that name, then the member name used to store + * the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value& operator[](const StaticString& key); +#ifdef JSON_USE_CPPTL + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const CppTL::ConstString& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const CppTL::ConstString& key) const; +#endif + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const char* key, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const std::string& key, const Value& defaultValue) const; +#ifdef JSON_USE_CPPTL + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const CppTL::ConstString& key, const Value& defaultValue) const; +#endif + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \return the removed Value, or null. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + /// \deprecated + Value removeMember(const char* key); + /// Same as removeMember(const char*) + /// \deprecated + Value removeMember(const std::string& key); + /** \brief Remove the named map member. + + Update 'removed' iff removed. + \return true iff removed (no exceptions) + */ + bool removeMember(const char* key, Value* removed); + /** \brief Remove the indexed array element. + + O(n) expensive operations. + Update 'removed' iff removed. + \return true iff removed (no exceptions) + */ + bool removeIndex(ArrayIndex i, Value* removed); + + /// Return true if the object has a member named key. + bool isMember(const char* key) const; + /// Return true if the object has a member named key. + bool isMember(const std::string& key) const; +#ifdef JSON_USE_CPPTL + /// Return true if the object has a member named key. + bool isMember(const CppTL::ConstString& key) const; +#endif + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + + //# ifdef JSON_USE_CPPTL + // EnumMemberNames enumMemberNames() const; + // EnumValues enumValues() const; + //# endif + + /// Comments must be //... or /* ... */ + void setComment(const char* comment, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const std::string& comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + std::string getComment(CommentPlacement placement) const; + + std::string toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + + // Accessors for the [start, limit) range of bytes within the JSON text from + // which this value was parsed, if any. + void setOffsetStart(size_t start); + void setOffsetLimit(size_t limit); + size_t getOffsetStart() const; + size_t getOffsetLimit() const; + +private: + void initBasic(ValueType type, bool allocated = false); + + Value& resolveReference(const char* key, bool isStatic); + +#ifdef JSON_VALUE_USE_INTERNAL_MAP + inline bool isItemAvailable() const { return itemIsUsed_ == 0; } + + inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; } + + inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } + + inline void setMemberNameIsStatic(bool isStatic) { + memberNameIsStatic_ = isStatic ? 1 : 0; + } +#endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP + +private: + struct CommentInfo { + CommentInfo(); + ~CommentInfo(); + + void setComment(const char* text); + + char* comment_; + }; + + // struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char* string_; +#ifdef JSON_VALUE_USE_INTERNAL_MAP + ValueInternalArray* array_; + ValueInternalMap* map_; +#else + ObjectValues* map_; +#endif + } value_; + ValueType type_ : 8; + int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. +#ifdef JSON_VALUE_USE_INTERNAL_MAP + unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. + int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. +#endif + CommentInfo* comments_; + + // [start, limit) byte offsets in the source JSON text from which this Value + // was extracted. + size_t start_; + size_t limit_; +}; + +/** \brief Experimental and untested: represents an element of the "path" to + * access a node. + */ +class JSON_API PathArgument { +public: + friend class Path; + + PathArgument(); + PathArgument(ArrayIndex index); + PathArgument(const char* key); + PathArgument(const std::string& key); + +private: + enum Kind { + kindNone = 0, + kindIndex, + kindKey + }; + std::string key_; + ArrayIndex index_; + Kind kind_; +}; + +/** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provied as parameter + */ +class JSON_API Path { +public: + Path(const std::string& path, + const PathArgument& a1 = PathArgument(), + const PathArgument& a2 = PathArgument(), + const PathArgument& a3 = PathArgument(), + const PathArgument& a4 = PathArgument(), + const PathArgument& a5 = PathArgument()); + + const Value& resolve(const Value& root) const; + Value resolve(const Value& root, const Value& defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on + /// the node. + Value& make(Value& root) const; + +private: + typedef std::vector InArgs; + typedef std::vector Args; + + void makePath(const std::string& path, const InArgs& in); + void addPathInArg(const std::string& path, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind); + void invalidPath(const std::string& path, int location); + + Args args_; +}; + +#ifdef JSON_VALUE_USE_INTERNAL_MAP +/** \brief Allocator to customize Value internal map. + * Below is an example of a simple implementation (default implementation + actually + * use memory pool for speed). + * \code + class DefaultValueMapAllocator : public ValueMapAllocator + { + public: // overridden from ValueMapAllocator + virtual ValueInternalMap *newMap() + { + return new ValueInternalMap(); + } + + virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) + { + return new ValueInternalMap( other ); + } + + virtual void destructMap( ValueInternalMap *map ) + { + delete map; + } + + virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) + { + return new ValueInternalLink[size]; + } + + virtual void releaseMapBuckets( ValueInternalLink *links ) + { + delete [] links; + } + + virtual ValueInternalLink *allocateMapLink() + { + return new ValueInternalLink(); + } + + virtual void releaseMapLink( ValueInternalLink *link ) + { + delete link; + } + }; + * \endcode + */ +class JSON_API ValueMapAllocator { +public: + virtual ~ValueMapAllocator(); + virtual ValueInternalMap* newMap() = 0; + virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) = 0; + virtual void destructMap(ValueInternalMap* map) = 0; + virtual ValueInternalLink* allocateMapBuckets(unsigned int size) = 0; + virtual void releaseMapBuckets(ValueInternalLink* links) = 0; + virtual ValueInternalLink* allocateMapLink() = 0; + virtual void releaseMapLink(ValueInternalLink* link) = 0; +}; + +/** \brief ValueInternalMap hash-map bucket chain link (for internal use only). + * \internal previous_ & next_ allows for bidirectional traversal. + */ +class JSON_API ValueInternalLink { +public: + enum { + itemPerLink = 6 + }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. + enum InternalFlags { + flagAvailable = 0, + flagUsed = 1 + }; + + ValueInternalLink(); + + ~ValueInternalLink(); + + Value items_[itemPerLink]; + char* keys_[itemPerLink]; + ValueInternalLink* previous_; + ValueInternalLink* next_; +}; + +/** \brief A linked page based hash-table implementation used internally by + *Value. + * \internal ValueInternalMap is a tradional bucket based hash-table, with a + *linked + * list in each bucket to handle collision. There is an addional twist in that + * each node of the collision linked list is a page containing a fixed amount of + * value. This provides a better compromise between memory usage and speed. + * + * Each bucket is made up of a chained list of ValueInternalLink. The last + * link of a given bucket can be found in the 'previous_' field of the following + *bucket. + * The last link of the last bucket is stored in tailLink_ as it has no + *following bucket. + * Only the last link of a bucket may contains 'available' item. The last link + *always + * contains at least one element unless is it the bucket one very first link. + */ +class JSON_API ValueInternalMap { + friend class ValueIteratorBase; + friend class Value; + +public: + typedef unsigned int HashKey; + typedef unsigned int BucketIndex; + +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + struct IteratorState { + IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {} + ValueInternalMap* map_; + ValueInternalLink* link_; + BucketIndex itemIndex_; + BucketIndex bucketIndex_; + }; +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + + ValueInternalMap(); + ValueInternalMap(const ValueInternalMap& other); + ValueInternalMap& operator=(ValueInternalMap other); + ~ValueInternalMap(); + + void swap(ValueInternalMap& other); + + BucketIndex size() const; + + void clear(); + + bool reserveDelta(BucketIndex growth); + + bool reserve(BucketIndex newItemCount); + + const Value* find(const char* key) const; + + Value* find(const char* key); + + Value& resolveReference(const char* key, bool isStatic); + + void remove(const char* key); + + void doActualRemove(ValueInternalLink* link, + BucketIndex index, + BucketIndex bucketIndex); + + ValueInternalLink*& getLastLinkInBucket(BucketIndex bucketIndex); + + Value& setNewItem(const char* key, + bool isStatic, + ValueInternalLink* link, + BucketIndex index); + + Value& unsafeAdd(const char* key, bool isStatic, HashKey hashedKey); + + HashKey hash(const char* key) const; + + int compare(const ValueInternalMap& other) const; + +private: + void makeBeginIterator(IteratorState& it) const; + void makeEndIterator(IteratorState& it) const; + static bool equals(const IteratorState& x, const IteratorState& other); + static void increment(IteratorState& iterator); + static void incrementBucket(IteratorState& iterator); + static void decrement(IteratorState& iterator); + static const char* key(const IteratorState& iterator); + static const char* key(const IteratorState& iterator, bool& isStatic); + static Value& value(const IteratorState& iterator); + static int distance(const IteratorState& x, const IteratorState& y); + +private: + ValueInternalLink* buckets_; + ValueInternalLink* tailLink_; + BucketIndex bucketsSize_; + BucketIndex itemCount_; +}; + +/** \brief A simplified deque implementation used internally by Value. +* \internal +* It is based on a list of fixed "page", each page contains a fixed number of +*items. +* Instead of using a linked-list, a array of pointer is used for fast item +*look-up. +* Look-up for an element is as follow: +* - compute page index: pageIndex = itemIndex / itemsPerPage +* - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] +* +* Insertion is amortized constant time (only the array containing the index of +*pointers +* need to be reallocated when items are appended). +*/ +class JSON_API ValueInternalArray { + friend class Value; + friend class ValueIteratorBase; + +public: + enum { + itemsPerPage = 8 + }; // should be a power of 2 for fast divide and modulo. + typedef Value::ArrayIndex ArrayIndex; + typedef unsigned int PageIndex; + +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + struct IteratorState // Must be a POD + { + IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {} + ValueInternalArray* array_; + Value** currentPageIndex_; + unsigned int currentItemIndex_; + }; +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + + ValueInternalArray(); + ValueInternalArray(const ValueInternalArray& other); + ValueInternalArray& operator=(ValueInternalArray other); + ~ValueInternalArray(); + void swap(ValueInternalArray& other); + + void clear(); + void resize(ArrayIndex newSize); + + Value& resolveReference(ArrayIndex index); + + Value* find(ArrayIndex index) const; + + ArrayIndex size() const; + + int compare(const ValueInternalArray& other) const; + +private: + static bool equals(const IteratorState& x, const IteratorState& other); + static void increment(IteratorState& iterator); + static void decrement(IteratorState& iterator); + static Value& dereference(const IteratorState& iterator); + static Value& unsafeDereference(const IteratorState& iterator); + static int distance(const IteratorState& x, const IteratorState& y); + static ArrayIndex indexOf(const IteratorState& iterator); + void makeBeginIterator(IteratorState& it) const; + void makeEndIterator(IteratorState& it) const; + void makeIterator(IteratorState& it, ArrayIndex index) const; + + void makeIndexValid(ArrayIndex index); + + Value** pages_; + ArrayIndex size_; + PageIndex pageCount_; +}; + +/** \brief Experimental: do not use. Allocator to customize Value internal +array. + * Below is an example of a simple implementation (actual implementation use + * memory pool). + \code +class DefaultValueArrayAllocator : public ValueArrayAllocator +{ +public: // overridden from ValueArrayAllocator +virtual ~DefaultValueArrayAllocator() +{ +} + +virtual ValueInternalArray *newArray() +{ + return new ValueInternalArray(); +} + +virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) +{ + return new ValueInternalArray( other ); +} + +virtual void destruct( ValueInternalArray *array ) +{ + delete array; +} + +virtual void reallocateArrayPageIndex( Value **&indexes, + ValueInternalArray::PageIndex +&indexCount, + ValueInternalArray::PageIndex +minNewIndexCount ) +{ + ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; + if ( minNewIndexCount > newIndexCount ) + newIndexCount = minNewIndexCount; + void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); + if ( !newIndexes ) + throw std::bad_alloc(); + indexCount = newIndexCount; + indexes = static_cast( newIndexes ); +} +virtual void releaseArrayPageIndex( Value **indexes, + ValueInternalArray::PageIndex indexCount ) +{ + if ( indexes ) + free( indexes ); +} + +virtual Value *allocateArrayPage() +{ + return static_cast( malloc( sizeof(Value) * +ValueInternalArray::itemsPerPage ) ); +} + +virtual void releaseArrayPage( Value *value ) +{ + if ( value ) + free( value ); +} +}; + \endcode + */ +class JSON_API ValueArrayAllocator { +public: + virtual ~ValueArrayAllocator(); + virtual ValueInternalArray* newArray() = 0; + virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) = 0; + virtual void destructArray(ValueInternalArray* array) = 0; + /** \brief Reallocate array page index. + * Reallocates an array of pointer on each page. + * \param indexes [input] pointer on the current index. May be \c NULL. + * [output] pointer on the new index of at least + * \a minNewIndexCount pages. + * \param indexCount [input] current number of pages in the index. + * [output] number of page the reallocated index can handle. + * \b MUST be >= \a minNewIndexCount. + * \param minNewIndexCount Minimum number of page the new index must be able + * to + * handle. + */ + virtual void + reallocateArrayPageIndex(Value**& indexes, + ValueInternalArray::PageIndex& indexCount, + ValueInternalArray::PageIndex minNewIndexCount) = 0; + virtual void + releaseArrayPageIndex(Value** indexes, + ValueInternalArray::PageIndex indexCount) = 0; + virtual Value* allocateArrayPage() = 0; + virtual void releaseArrayPage(Value* value) = 0; +}; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + +/** \brief base class for Value iterators. + * + */ +class JSON_API ValueIteratorBase { +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef unsigned int size_t; + typedef int difference_type; + typedef ValueIteratorBase SelfType; + + ValueIteratorBase(); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); +#else + ValueIteratorBase(const ValueInternalArray::IteratorState& state); + ValueIteratorBase(const ValueInternalMap::IteratorState& state); +#endif + + bool operator==(const SelfType& other) const { return isEqual(other); } + + bool operator!=(const SelfType& other) const { return !isEqual(other); } + + difference_type operator-(const SelfType& other) const { + return computeDistance(other); + } + + /// Return either the index or the member name of the referenced value as a + /// Value. + Value key() const; + + /// Return the index of the referenced Value. -1 if it is not an arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value. "" if it is not an + /// objectValue. + const char* memberName() const; + +protected: + Value& deref() const; + + void increment(); + + void decrement(); + + difference_type computeDistance(const SelfType& other) const; + + bool isEqual(const SelfType& other) const; + + void copy(const SelfType& other); + +private: +#ifndef JSON_VALUE_USE_INTERNAL_MAP + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_; +#else + union { + ValueInternalArray::IteratorState array_; + ValueInternalMap::IteratorState map_; + } iterator_; + bool isArray_; +#endif +}; + +/** \brief const iterator for object and array value. + * + */ +class JSON_API ValueConstIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef const Value value_type; + typedef unsigned int size_t; + typedef int difference_type; + typedef const Value& reference; + typedef const Value* pointer; + typedef ValueConstIterator SelfType; + + ValueConstIterator(); + +private: +/*! \internal Use by Value to create an iterator. + */ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueConstIterator(const Value::ObjectValues::iterator& current); +#else + ValueConstIterator(const ValueInternalArray::IteratorState& state); + ValueConstIterator(const ValueInternalMap::IteratorState& state); +#endif +public: + SelfType& operator=(const ValueIteratorBase& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +/** \brief Iterator for object and array value. + */ +class JSON_API ValueIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef Value value_type; + typedef unsigned int size_t; + typedef int difference_type; + typedef Value& reference; + typedef Value* pointer; + typedef ValueIterator SelfType; + + ValueIterator(); + ValueIterator(const ValueConstIterator& other); + ValueIterator(const ValueIterator& other); + +private: +/*! \internal Use by Value to create an iterator. + */ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueIterator(const Value::ObjectValues::iterator& current); +#else + ValueIterator(const ValueInternalArray::IteratorState& state); + ValueIterator(const ValueInternalMap::IteratorState& state); +#endif +public: + SelfType& operator=(const SelfType& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +} // namespace Json + + +namespace std { +/// Specialize std::swap() for Json::Value. +template<> +inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } +} + + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_READER_H_INCLUDED +#define CPPTL_JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "features.h" +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +namespace Json { + +/** \brief Unserialize a JSON document into a + *Value. + * + */ +class JSON_API Reader { +public: + typedef char Char; + typedef const Char* Location; + + /** \brief An error tagged with where in the JSON text it was encountered. + * + * The offsets give the [start, limit) range of bytes within the text. Note + * that this is bytes, not codepoints. + * + */ + struct StructuredError { + size_t offset_start; + size_t offset_limit; + std::string message; + }; + + /** \brief Constructs a Reader allowing all features + * for parsing. + */ + Reader(); + + /** \brief Constructs a Reader allowing the specified feature set + * for parsing. + */ + Reader(const Features& features); + + /** \brief Read a Value from a JSON + * document. + * \param document UTF-8 encoded string containing the document to read. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + * back during + * serialization, \c false to discard comments. + * This parameter is ignored if + * Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool + parse(const std::string& document, Value& root, bool collectComments = true); + + /** \brief Read a Value from a JSON + document. + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + \ Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + back during + * serialization, \c false to discard comments. + * This parameter is ignored if + Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse(std::istream& is, Value& root, bool collectComments = true); + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + * \deprecated Use getFormattedErrorMessages() instead (typo fix). + */ + JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") + std::string getFormatedErrorMessages() const; + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + */ + std::string getFormattedErrorMessages() const; + + /** \brief Returns a vector of structured erros encounted while parsing. + * \return A (possibly empty) vector of StructuredError objects. Currently + * only one error can be returned, but the caller should tolerate + * multiple + * errors. This can occur if the parser recovers from a non-fatal + * parse error and then encounters additional errors. + */ + std::vector getStructuredErrors() const; + + /** \brief Add a semantic error message. + * \param value JSON Value location associated with the error + * \param message The error message. + * \return \c true if the error was successfully added, \c false if the + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, const std::string& message); + + /** \brief Add a semantic error message with extra context. + * \param value JSON Value location associated with the error + * \param message The error message. + * \param extra Additional JSON Value location to contextualize the error + * \return \c true if the error was successfully added, \c false if either + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, const std::string& message, const Value& extra); + + /** \brief Return whether there are any errors. + * \return \c true if there are no errors to report \c false if + * errors have occurred. + */ + bool good() const; + +private: + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + std::string message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, std::string& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool addError(const std::string& message, Token& token, Location extra = 0); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void + getLocationLineAndColumn(Location location, int& line, int& column) const; + std::string getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + std::string document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + std::string commentsBefore_; + Features features_; + bool collectComments_; +}; + +/** \brief Read from 'sin' into 'root'. + + Always keep comments from the input JSON. + + This can be used to read a file into a particular sub-object. + For example: + \code + Json::Value root; + cin >> root["dir"]["file"]; + cout << root; + \endcode + Result: + \verbatim + { + "dir": { + "file": { + // The input stream JSON would be nested here. + } + } + } + \endverbatim + \throw std::exception on parse error. + \see Json::operator<<() +*/ +JSON_API std::istream& operator>>(std::istream&, Value&); + +} // namespace Json + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_READER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +#define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +namespace Json { + +class Value; + +/** \brief Abstract class for writers. + */ +class JSON_API Writer { +public: + virtual ~Writer(); + + virtual std::string write(const Value& root) = 0; +}; + +/** \brief Outputs a Value in JSON format + *without formatting (not human friendly). + * + * The JSON document is written in a single line. It is not intended for 'human' + *consumption, + * but may be usefull to support feature such as RPC where bandwith is limited. + * \sa Reader, Value + */ +class JSON_API FastWriter : public Writer { +public: + FastWriter(); + virtual ~FastWriter() {} + + void enableYAMLCompatibility(); + + /** \brief Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's Javascript, it makes for smaller output and the + * browser can handle the output just fine. + */ + void dropNullPlaceholders(); + + void omitEndingLineFeed(); + +public: // overridden from Writer + virtual std::string write(const Value& root); + +private: + void writeValue(const Value& value); + + std::string document_; + bool yamlCompatiblityEnabled_; + bool dropNullPlaceholders_; + bool omitEndingLineFeed_; +}; + +/** \brief Writes a Value in JSON format in a + *human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + *line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + *types, + * and all the values fit on one lines, then print the array on a single + *line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + *#CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + */ +class JSON_API StyledWriter : public Writer { +public: + StyledWriter(); + virtual ~StyledWriter() {} + +public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + virtual std::string write(const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultineArray(const Value& value); + void pushValue(const std::string& value); + void writeIndent(); + void writeWithIndent(const std::string& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + bool hasCommentForValue(const Value& value); + static std::string normalizeEOL(const std::string& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::string document_; + std::string indentString_; + int rightMargin_; + int indentSize_; + bool addChildValues_; +}; + +/** \brief Writes a Value in JSON format in a + human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + types, + * and all the values fit on one lines, then print the array on a single + line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + #CommentPlacement. + * + * \param indentation Each level will be indented by this amount extra. + * \sa Reader, Value, Value::setComment() + */ +class JSON_API StyledStreamWriter { +public: + StyledStreamWriter(std::string indentation = "\t"); + ~StyledStreamWriter() {} + +public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not + * return a value. + */ + void write(std::ostream& out, const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultineArray(const Value& value); + void pushValue(const std::string& value); + void writeIndent(); + void writeWithIndent(const std::string& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + bool hasCommentForValue(const Value& value); + static std::string normalizeEOL(const std::string& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::ostream* document_; + std::string indentString_; + int rightMargin_; + std::string indentation_; + bool addChildValues_; +}; + +#if defined(JSON_HAS_INT64) +std::string JSON_API valueToString(Int value); +std::string JSON_API valueToString(UInt value); +#endif // if defined(JSON_HAS_INT64) +std::string JSON_API valueToString(LargestInt value); +std::string JSON_API valueToString(LargestUInt value); +std::string JSON_API valueToString(double value); +std::string JSON_API valueToString(bool value); +std::string JSON_API valueToQuotedString(const char* value); + +/// \brief Output using the StyledStreamWriter. +/// \see Json::operator>>() +JSON_API std::ostream& operator<<(std::ostream&, const Value& root); + +} // namespace Json + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_WRITER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED +#define CPPTL_JSON_ASSERTIONS_H_INCLUDED + +#include +#include + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +#if JSON_USE_EXCEPTION +#include +#define JSON_ASSERT(condition) \ + assert(condition); // @todo <= change this into an exception throw +#define JSON_FAIL_MESSAGE(message) do{std::ostringstream oss; oss << message; throw std::runtime_error(oss.str());}while(0) +//#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message) +#else // JSON_USE_EXCEPTION +#define JSON_ASSERT(condition) assert(condition); + +// The call to assert() will show the failure message in debug builds. In +// release bugs we abort, for a core-dump or debugger. +#define JSON_FAIL_MESSAGE(message) \ + { \ + std::ostringstream oss; oss << message; \ + assert(false && oss.str().c_str()); \ + abort(); \ + } + + +#endif + +#define JSON_ASSERT_MESSAGE(condition, message) \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } + +#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_AMALGATED_H_INCLUDED diff --git a/jsoncpp/jsoncpp.cpp b/jsoncpp/jsoncpp.cpp new file mode 100644 index 0000000..ba2f5ca --- /dev/null +++ b/jsoncpp/jsoncpp.cpp @@ -0,0 +1,3691 @@ +/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + + +#include "jsoncpp/json.h" + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +/* This header provides common string manipulation support, such as UTF-8, + * portable conversion from/to string... + * + * It is an internal header that must not be exposed. + */ + +namespace Json { + +/// Converts a unicode code-point to UTF-8. +static inline std::string codePointToUTF8(unsigned int cp) { + std::string result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) { + result.resize(1); + result[0] = static_cast(cp); + } else if (cp <= 0x7FF) { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } else if (cp <= 0xFFFF) { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); + result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + + return result; +} + +/// Returns true if ch is a control character (in range [0,32[). +static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } + +enum { + /// Constant that specify the size of the buffer that must be passed to + /// uintToString. + uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 +}; + +// Defines a char buffer for use with uintToString(). +typedef char UIntToStringBuffer[uintToStringBufferSize]; + +/** Converts an unsigned integer to string. + * @param value Unsigned interger to convert to string + * @param current Input/Output string buffer. + * Must have at least uintToStringBufferSize chars free. + */ +static inline void uintToString(LargestUInt value, char*& current) { + *--current = 0; + do { + *--current = char(value % 10) + '0'; + value /= 10; + } while (value != 0); +} + +/** Change ',' to '.' everywhere in buffer. + * + * We had a sophisticated way, but it did not work in WinCE. + * @see https://github.com/open-source-parsers/jsoncpp/pull/9 + */ +static inline void fixNumericLocale(char* begin, char* end) { + while (begin < end) { + if (*begin == ',') { + *begin = '.'; + } + ++begin; + } +} + +} // namespace Json { + +#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below +#define snprintf _snprintf +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +namespace Json { + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() + : allowComments_(true), strictRoot_(false), + allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} + +Features Features::all() { return Features(); } + +Features Features::strictMode() { + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + features.allowDroppedNullPlaceholders_ = false; + features.allowNumericKeys_ = false; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + +static bool containsNewLine(Reader::Location begin, Reader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; +} + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(Features::all()), + collectComments_() {} + +Reader::Reader(const Features& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool +Reader::parse(const std::string& document, Value& root, bool collectComments) { + document_ = document; + const char* begin = document_.c_str(); + const char* end = begin + document_.length(); + return parse(begin, end, root, collectComments); +} + +bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { + // std::istream_iterator begin(sin); + // std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since std::string is reference-counted, this at least does not + // create an extra copy. + std::string doc; + std::getline(sin, doc, (char)EOF); + return parse(doc, root, collectComments); +} + +bool Reader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_ = ""; + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool Reader::readValue() { + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + // Remove newline at the end of the comment + if (commentsBefore_[commentsBefore_.size() - 1] == '\n') + commentsBefore_.resize(commentsBefore_.size() - 1); + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_ = ""; + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenFalse: + { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenNull: + { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenArraySeparator: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } + // Else, fall through... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + +void Reader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool Reader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool Reader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool Reader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +static std::string normalizeEOL(Reader::Location begin, Reader::Location end) { + std::string normalized; + normalized.reserve(end - begin); + Reader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void +Reader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); + const std::string& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool Reader::readCStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +void Reader::readNumber() { + const char *p = current_; + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : 0; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } +} + +bool Reader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool Reader::readObject(Token& tokenStart) { + Token tokenName; + std::string name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name = ""; + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover( + "Missing ':' after object member name", colon, tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover( + "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover( + "Missing '}' or object member name", tokenName, tokenObjectEnd); +} + +bool Reader::readArray(Token& tokenStart) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + skipSpaces(); + if (*current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token token; + // Accept Comment after last item in the array. + ok = readToken(token); + while (token.type_ == tokenComment && ok) { + ok = readToken(token); + } + bool badTokenType = + (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover( + "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + } + if (token.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool Reader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(-Value::minLargestInt) + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(c - '0'); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool Reader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + const int bufferSize = 32; + int count; + int length = int(token.end_ - token.start_); + + // Sanity check to avoid buffer overflow exploits. + if (length < 0) { + return addError("Unable to parse token length", token); + } + + // Avoid using a string constant for the format control string given to + // sscanf, as this can cause hard to debug crashes on OS X. See here for more + // info: + // + // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html + char format[] = "%lf"; + + if (length <= bufferSize) { + Char buffer[bufferSize + 1]; + memcpy(buffer, token.start_, length); + buffer[length] = 0; + count = sscanf(buffer, format, &value); + } else { + std::string buffer(token.start_, token.end_); + count = sscanf(buffer.c_str(), format, &value); + } + + if (count != 1) + return addError("'" + std::string(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool Reader::decodeString(Token& token) { + std::string decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeString(Token& token, std::string& decoded) { + decoded.reserve(token.end_ - token.start_ - 2); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool Reader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, + current); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++) == 'u') { + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, + current); + } + return true; +} + +bool Reader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", + token, + current); + unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, + current); + } + return true; +} + +bool +Reader::addError(const std::string& message, Token& token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool Reader::recoverFromError(TokenType skipUntilToken) { + int errorCount = int(errors_.size()); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool Reader::addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& Reader::currentValue() { return *(nodes_.top()); } + +Reader::Char Reader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void Reader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +std::string Reader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) +#if defined(WINCE) + _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#else + sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#endif +#else + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#endif + return buffer; +} + +// Deprecated. Preserved for backward compatibility +std::string Reader::getFormatedErrorMessages() const { + return getFormattedErrorMessages(); +} + +std::string Reader::getFormattedErrorMessages() const { + std::string formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector Reader::getStructuredErrors() const { + std::vector allErrors; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + Reader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +bool Reader::pushError(const Value& value, const std::string& message) { + size_t length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = 0; + errors_.push_back(info); + return true; +} + +bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) { + size_t length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length + || extra.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); + return true; +} + +bool Reader::good() const { + return !errors_.size(); +} + +std::istream& operator>>(std::istream& sin, Value& root) { + Json::Reader reader; + bool ok = reader.parse(sin, root, true); + if (!ok) { + fprintf(stderr, + "Error from reader: %s", + reader.getFormattedErrorMessages().c_str()); + + JSON_FAIL_MESSAGE("reader error"); + } + return sin; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_batchallocator.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED +#define JSONCPP_BATCHALLOCATOR_H_INCLUDED + +#include +#include + +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +namespace Json { + +/* Fast memory allocator. + * + * This memory allocator allocates memory for a batch of object (specified by + * the page size, the number of object in each page). + * + * It does not allow the destruction of a single object. All the allocated + * objects can be destroyed at once. The memory can be either released or reused + * for future allocation. + * + * The in-place new operator must be used to construct the object using the + * pointer returned by allocate. + */ +template +class BatchAllocator { +public: + BatchAllocator(unsigned int objectsPerPage = 255) + : freeHead_(0), objectsPerPage_(objectsPerPage) { + // printf( "Size: %d => %s\n", sizeof(AllocatedType), + // typeid(AllocatedType).name() ); + assert(sizeof(AllocatedType) * objectPerAllocation >= + sizeof(AllocatedType*)); // We must be able to store a slist in the + // object free space. + assert(objectsPerPage >= 16); + batches_ = allocateBatch(0); // allocated a dummy page + currentBatch_ = batches_; + } + + ~BatchAllocator() { + for (BatchInfo* batch = batches_; batch;) { + BatchInfo* nextBatch = batch->next_; + free(batch); + batch = nextBatch; + } + } + + /// allocate space for an array of objectPerAllocation object. + /// @warning it is the responsability of the caller to call objects + /// constructors. + AllocatedType* allocate() { + if (freeHead_) // returns node from free list. + { + AllocatedType* object = freeHead_; + freeHead_ = *(AllocatedType**)object; + return object; + } + if (currentBatch_->used_ == currentBatch_->end_) { + currentBatch_ = currentBatch_->next_; + while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_) + currentBatch_ = currentBatch_->next_; + + if (!currentBatch_) // no free batch found, allocate a new one + { + currentBatch_ = allocateBatch(objectsPerPage_); + currentBatch_->next_ = batches_; // insert at the head of the list + batches_ = currentBatch_; + } + } + AllocatedType* allocated = currentBatch_->used_; + currentBatch_->used_ += objectPerAllocation; + return allocated; + } + + /// Release the object. + /// @warning it is the responsability of the caller to actually destruct the + /// object. + void release(AllocatedType* object) { + assert(object != 0); + *(AllocatedType**)object = freeHead_; + freeHead_ = object; + } + +private: + struct BatchInfo { + BatchInfo* next_; + AllocatedType* used_; + AllocatedType* end_; + AllocatedType buffer_[objectPerAllocation]; + }; + + // disabled copy constructor and assignement operator. + BatchAllocator(const BatchAllocator&); + void operator=(const BatchAllocator&); + + static BatchInfo* allocateBatch(unsigned int objectsPerPage) { + const unsigned int mallocSize = + sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation + + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; + BatchInfo* batch = static_cast(malloc(mallocSize)); + batch->next_ = 0; + batch->used_ = batch->buffer_; + batch->end_ = batch->buffer_ + objectsPerPage; + return batch; + } + + BatchInfo* batches_; + BatchInfo* currentBatch_; + /// Head of a single linked list within the allocated space of freeed object + AllocatedType* freeHead_; + unsigned int objectsPerPage_; +}; + +} // namespace Json + +#endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION + +#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_batchallocator.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +// included by json_value.cpp + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIteratorBase +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIteratorBase::ValueIteratorBase() +#ifndef JSON_VALUE_USE_INTERNAL_MAP + : current_(), isNull_(true) { +} +#else + : isArray_(true), isNull_(true) { + iterator_.array_ = ValueInternalArray::IteratorState(); +} +#endif + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueIteratorBase::ValueIteratorBase( + const Value::ObjectValues::iterator& current) + : current_(current), isNull_(false) {} +#else +ValueIteratorBase::ValueIteratorBase( + const ValueInternalArray::IteratorState& state) + : isArray_(true) { + iterator_.array_ = state; +} + +ValueIteratorBase::ValueIteratorBase( + const ValueInternalMap::IteratorState& state) + : isArray_(false) { + iterator_.map_ = state; +} +#endif + +Value& ValueIteratorBase::deref() const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + return current_->second; +#else + if (isArray_) + return ValueInternalArray::dereference(iterator_.array_); + return ValueInternalMap::value(iterator_.map_); +#endif +} + +void ValueIteratorBase::increment() { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ++current_; +#else + if (isArray_) + ValueInternalArray::increment(iterator_.array_); + ValueInternalMap::increment(iterator_.map_); +#endif +} + +void ValueIteratorBase::decrement() { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + --current_; +#else + if (isArray_) + ValueInternalArray::decrement(iterator_.array_); + ValueInternalMap::decrement(iterator_.map_); +#endif +} + +ValueIteratorBase::difference_type +ValueIteratorBase::computeDistance(const SelfType& other) const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP +#ifdef JSON_USE_CPPTL_SMALLMAP + return current_ - other.current_; +#else + // Iterator for null value are initialized using the default + // constructor, which initialize current_ to the default + // std::map::iterator. As begin() and end() are two instance + // of the default std::map::iterator, they can not be compared. + // To allow this, we handle this comparison specifically. + if (isNull_ && other.isNull_) { + return 0; + } + + // Usage of std::distance is not portable (does not compile with Sun Studio 12 + // RogueWave STL, + // which is the one used by default). + // Using a portable hand-made version for non random iterator instead: + // return difference_type( std::distance( current_, other.current_ ) ); + difference_type myDistance = 0; + for (Value::ObjectValues::iterator it = current_; it != other.current_; + ++it) { + ++myDistance; + } + return myDistance; +#endif +#else + if (isArray_) + return ValueInternalArray::distance(iterator_.array_, + other.iterator_.array_); + return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_); +#endif +} + +bool ValueIteratorBase::isEqual(const SelfType& other) const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + if (isNull_) { + return other.isNull_; + } + return current_ == other.current_; +#else + if (isArray_) + return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_); + return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_); +#endif +} + +void ValueIteratorBase::copy(const SelfType& other) { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + current_ = other.current_; + isNull_ = other.isNull_; +#else + if (isArray_) + iterator_.array_ = other.iterator_.array_; + iterator_.map_ = other.iterator_.map_; +#endif +} + +Value ValueIteratorBase::key() const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const Value::CZString czstring = (*current_).first; + if (czstring.c_str()) { + if (czstring.isStaticString()) + return Value(StaticString(czstring.c_str())); + return Value(czstring.c_str()); + } + return Value(czstring.index()); +#else + if (isArray_) + return Value(ValueInternalArray::indexOf(iterator_.array_)); + bool isStatic; + const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic); + if (isStatic) + return Value(StaticString(memberName)); + return Value(memberName); +#endif +} + +UInt ValueIteratorBase::index() const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const Value::CZString czstring = (*current_).first; + if (!czstring.c_str()) + return czstring.index(); + return Value::UInt(-1); +#else + if (isArray_) + return Value::UInt(ValueInternalArray::indexOf(iterator_.array_)); + return Value::UInt(-1); +#endif +} + +const char* ValueIteratorBase::memberName() const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const char* name = (*current_).first.c_str(); + return name ? name : ""; +#else + if (!isArray_) + return ValueInternalMap::key(iterator_.map_); + return ""; +#endif +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueConstIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueConstIterator::ValueConstIterator() {} + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueConstIterator::ValueConstIterator( + const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} +#else +ValueConstIterator::ValueConstIterator( + const ValueInternalArray::IteratorState& state) + : ValueIteratorBase(state) {} + +ValueConstIterator::ValueConstIterator( + const ValueInternalMap::IteratorState& state) + : ValueIteratorBase(state) {} +#endif + +ValueConstIterator& ValueConstIterator:: +operator=(const ValueIteratorBase& other) { + copy(other); + return *this; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIterator::ValueIterator() {} + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} +#else +ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state) + : ValueIteratorBase(state) {} + +ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state) + : ValueIteratorBase(state) {} +#endif + +ValueIterator::ValueIterator(const ValueConstIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator::ValueIterator(const ValueIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator& ValueIterator::operator=(const SelfType& other) { + copy(other); + return *this; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR +#include "json_batchallocator.h" +#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#ifdef JSON_USE_CPPTL +#include +#endif +#include // size_t + +#define JSON_ASSERT_UNREACHABLE assert(false) + +namespace Json { + +// This is a walkaround to avoid the static initialization of Value::null. +// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of +// 8 (instead of 4) as a bit of future-proofing. +#if defined(__ARMEL__) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#else +#define ALIGNAS(byte_alignment) +#endif +static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; +const unsigned char& kNullRef = kNull[0]; +const Value& Value::null = reinterpret_cast(kNullRef); + +const Int Value::minInt = Int(~(UInt(-1) / 2)); +const Int Value::maxInt = Int(UInt(-1) / 2); +const UInt Value::maxUInt = UInt(-1); +#if defined(JSON_HAS_INT64) +const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); +const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); +const UInt64 Value::maxUInt64 = UInt64(-1); +// The constant is hard-coded because some compiler have trouble +// converting Value::maxUInt64 to a double correctly (AIX/xlC). +// Assumes that UInt64 is a 64 bits integer. +static const double maxUInt64AsDouble = 18446744073709551615.0; +#endif // defined(JSON_HAS_INT64) +const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); +const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); +const LargestUInt Value::maxLargestUInt = LargestUInt(-1); + +/// Unknown size marker +static const unsigned int unknown = (unsigned)-1; + +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +template +static inline bool InRange(double d, T min, U max) { + return d >= min && d <= max; +} +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double integerToDouble(Json::UInt64 value) { + return static_cast(Int64(value / 2)) * 2.0 + Int64(value & 1); +} + +template static inline double integerToDouble(T value) { + return static_cast(value); +} + +template +static inline bool InRange(double d, T min, U max) { + return d >= integerToDouble(min) && d <= integerToDouble(max); +} +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + +/** Duplicates the specified string value. + * @param value Pointer to the string to duplicate. Must be zero-terminated if + * length is "unknown". + * @param length Length of the value. if equals to unknown, then it will be + * computed using strlen(value). + * @return Pointer on the duplicate instance of string. + */ +static inline char* duplicateStringValue(const char* value, + unsigned int length = unknown) { + if (length == unknown) + length = (unsigned int)strlen(value); + + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + if (length >= (unsigned)Value::maxInt) + length = Value::maxInt - 1; + + char* newString = static_cast(malloc(length + 1)); + JSON_ASSERT_MESSAGE(newString != 0, + "in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); + memcpy(newString, value, length); + newString[length] = 0; + return newString; +} + +/** Free the string duplicated by duplicateStringValue(). + */ +static inline void releaseStringValue(char* value) { free(value); } + +} // namespace Json + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ValueInternals... +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#if !defined(JSON_IS_AMALGAMATION) +#ifdef JSON_VALUE_USE_INTERNAL_MAP +#include "json_internalarray.inl" +#include "json_internalmap.inl" +#endif // JSON_VALUE_USE_INTERNAL_MAP + +#include "json_valueiterator.inl" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CommentInfo +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +Value::CommentInfo::CommentInfo() : comment_(0) {} + +Value::CommentInfo::~CommentInfo() { + if (comment_) + releaseStringValue(comment_); +} + +void Value::CommentInfo::setComment(const char* text) { + if (comment_) + releaseStringValue(comment_); + JSON_ASSERT(text != 0); + JSON_ASSERT_MESSAGE( + text[0] == '\0' || text[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + // It seems that /**/ style comments are acceptable as well. + comment_ = duplicateStringValue(text); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CZString +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#ifndef JSON_VALUE_USE_INTERNAL_MAP + +// Notes: index_ indicates if the string was allocated when +// a string is stored. + +Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} + +Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate) + : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr), + index_(allocate) {} + +Value::CZString::CZString(const CZString& other) + : cstr_(other.index_ != noDuplication && other.cstr_ != 0 + ? duplicateStringValue(other.cstr_) + : other.cstr_), + index_(other.cstr_ + ? static_cast(other.index_ == noDuplication + ? noDuplication : duplicate) + : other.index_) {} + +Value::CZString::~CZString() { + if (cstr_ && index_ == duplicate) + releaseStringValue(const_cast(cstr_)); +} + +void Value::CZString::swap(CZString& other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); +} + +Value::CZString& Value::CZString::operator=(CZString other) { + swap(other); + return *this; +} + +bool Value::CZString::operator<(const CZString& other) const { + if (cstr_) + return strcmp(cstr_, other.cstr_) < 0; + return index_ < other.index_; +} + +bool Value::CZString::operator==(const CZString& other) const { + if (cstr_) + return strcmp(cstr_, other.cstr_) == 0; + return index_ == other.index_; +} + +ArrayIndex Value::CZString::index() const { return index_; } + +const char* Value::CZString::c_str() const { return cstr_; } + +bool Value::CZString::isStaticString() const { return index_ == noDuplication; } + +#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::Value +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/*! \internal Default constructor initialization must be equivalent to: + * memset( this, 0, sizeof(Value) ) + * This optimization is used in ValueInternalMap fast allocator. + */ +Value::Value(ValueType type) { + initBasic(type); + switch (type) { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + value_.string_ = 0; + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; +#else + case arrayValue: + value_.array_ = arrayAllocator()->newArray(); + break; + case objectValue: + value_.map_ = mapAllocator()->newMap(); + break; +#endif + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +Value::Value(Int value) { + initBasic(intValue); + value_.int_ = value; +} + +Value::Value(UInt value) { + initBasic(uintValue); + value_.uint_ = value; +} +#if defined(JSON_HAS_INT64) +Value::Value(Int64 value) { + initBasic(intValue); + value_.int_ = value; +} +Value::Value(UInt64 value) { + initBasic(uintValue); + value_.uint_ = value; +} +#endif // defined(JSON_HAS_INT64) + +Value::Value(double value) { + initBasic(realValue); + value_.real_ = value; +} + +Value::Value(const char* value) { + initBasic(stringValue, true); + value_.string_ = duplicateStringValue(value); +} + +Value::Value(const char* beginValue, const char* endValue) { + initBasic(stringValue, true); + value_.string_ = + duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue)); +} + +Value::Value(const std::string& value) { + initBasic(stringValue, true); + value_.string_ = + duplicateStringValue(value.c_str(), (unsigned int)value.length()); +} + +Value::Value(const StaticString& value) { + initBasic(stringValue); + value_.string_ = const_cast(value.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value::Value(const CppTL::ConstString& value) { + initBasic(stringValue, true); + value_.string_ = duplicateStringValue(value, value.length()); +} +#endif + +Value::Value(bool value) { + initBasic(booleanValue); + value_.bool_ = value; +} + +Value::Value(const Value& other) + : type_(other.type_), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(other.start_), limit_(other.limit_) { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_) { + value_.string_ = duplicateStringValue(other.value_.string_); + allocated_ |= true; + } else { + value_.string_ = 0; + allocated_ = false; + } + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; +#else + case arrayValue: + value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_); + break; + case objectValue: + value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_); + break; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo& otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment(otherComment.comment_); + } + } +} + +Value::~Value() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releaseStringValue(value_.string_); + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + delete value_.map_; + break; +#else + case arrayValue: + arrayAllocator()->destructArray(value_.array_); + break; + case objectValue: + mapAllocator()->destructMap(value_.map_); + break; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + + if (comments_) + delete[] comments_; +} + +Value& Value::operator=(Value other) { + swap(other); + return *this; +} + +void Value::swapPayload(Value& other) { + ValueType temp = type_; + type_ = other.type_; + other.type_ = temp; + std::swap(value_, other.value_); + int temp2 = allocated_; + allocated_ = other.allocated_; + other.allocated_ = temp2; +} + +void Value::swap(Value& other) { + swapPayload(other); + std::swap(comments_, other.comments_); + std::swap(start_, other.start_); + std::swap(limit_, other.limit_); +} + +ValueType Value::type() const { return type_; } + +int Value::compare(const Value& other) const { + if (*this < other) + return -1; + if (*this > other) + return 1; + return 0; +} + +bool Value::operator<(const Value& other) const { + int typeDelta = type_ - other.type_; + if (typeDelta) + return typeDelta < 0 ? true : false; + switch (type_) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: + return (value_.string_ == 0 && other.value_.string_) || + (other.value_.string_ && value_.string_ && + strcmp(value_.string_, other.value_.string_) < 0); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: { + int delta = int(value_.map_->size() - other.value_.map_->size()); + if (delta) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } +#else + case arrayValue: + return value_.array_->compare(*(other.value_.array_)) < 0; + case objectValue: + return value_.map_->compare(*(other.value_.map_)) < 0; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator<=(const Value& other) const { return !(other < *this); } + +bool Value::operator>=(const Value& other) const { return !(*this < other); } + +bool Value::operator>(const Value& other) const { return other < *this; } + +bool Value::operator==(const Value& other) const { + // if ( type_ != other.type_ ) + // GCC 2.95.3 says: + // attempt to take address of bit-field structure member `Json::Value::type_' + // Beats me, but a temp solves the problem. + int temp = other.type_; + if (type_ != temp) + return false; + switch (type_) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: + return (value_.string_ == other.value_.string_) || + (other.value_.string_ && value_.string_ && + strcmp(value_.string_, other.value_.string_) == 0); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && + (*value_.map_) == (*other.value_.map_); +#else + case arrayValue: + return value_.array_->compare(*(other.value_.array_)) == 0; + case objectValue: + return value_.map_->compare(*(other.value_.map_)) == 0; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator!=(const Value& other) const { return !(*this == other); } + +const char* Value::asCString() const { + JSON_ASSERT_MESSAGE(type_ == stringValue, + "in Json::Value::asCString(): requires stringValue"); + return value_.string_; +} + +std::string Value::asString() const { + switch (type_) { + case nullValue: + return ""; + case stringValue: + return value_.string_ ? value_.string_ : ""; + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + return valueToString(value_.int_); + case uintValue: + return valueToString(value_.uint_); + case realValue: + return valueToString(value_.real_); + default: + JSON_FAIL_MESSAGE("Type is not convertible to string"); + } +} + +#ifdef JSON_USE_CPPTL +CppTL::ConstString Value::asConstString() const { + return CppTL::ConstString(asString().c_str()); +} +#endif + +Value::Int Value::asInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), + "double out of Int range"); + return Int(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int."); +} + +Value::UInt Value::asUInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), + "double out of UInt range"); + return UInt(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt."); +} + +#if defined(JSON_HAS_INT64) + +Value::Int64 Value::asInt64() const { + switch (type_) { + case intValue: + return Int64(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); + return Int64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), + "double out of Int64 range"); + return Int64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int64."); +} + +Value::UInt64 Value::asUInt64() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); + return UInt64(value_.int_); + case uintValue: + return UInt64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), + "double out of UInt64 range"); + return UInt64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); +} +#endif // if defined(JSON_HAS_INT64) + +LargestInt Value::asLargestInt() const { +#if defined(JSON_NO_INT64) + return asInt(); +#else + return asInt64(); +#endif +} + +LargestUInt Value::asLargestUInt() const { +#if defined(JSON_NO_INT64) + return asUInt(); +#else + return asUInt64(); +#endif +} + +double Value::asDouble() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return value_.real_; + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to double."); +} + +float Value::asFloat() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return static_cast(value_.real_); + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0f : 0.0f; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to float."); +} + +bool Value::asBool() const { + switch (type_) { + case booleanValue: + return value_.bool_; + case nullValue: + return false; + case intValue: + return value_.int_ ? true : false; + case uintValue: + return value_.uint_ ? true : false; + case realValue: + return value_.real_ ? true : false; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to bool."); +} + +bool Value::isConvertibleTo(ValueType other) const { + switch (other) { + case nullValue: + return (isNumeric() && asDouble() == 0.0) || + (type_ == booleanValue && value_.bool_ == false) || + (type_ == stringValue && asString() == "") || + (type_ == arrayValue && value_.map_->size() == 0) || + (type_ == objectValue && value_.map_->size() == 0) || + type_ == nullValue; + case intValue: + return isInt() || + (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || + type_ == booleanValue || type_ == nullValue; + case uintValue: + return isUInt() || + (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || + type_ == booleanValue || type_ == nullValue; + case realValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case booleanValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case stringValue: + return isNumeric() || type_ == booleanValue || type_ == stringValue || + type_ == nullValue; + case arrayValue: + return type_ == arrayValue || type_ == nullValue; + case objectValue: + return type_ == objectValue || type_ == nullValue; + } + JSON_ASSERT_UNREACHABLE; + return false; +} + +/// Number of values in array or object +ArrayIndex Value::size() const { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return ArrayIndex(value_.map_->size()); +#else + case arrayValue: + return Int(value_.array_->size()); + case objectValue: + return Int(value_.map_->size()); +#endif + } + JSON_ASSERT_UNREACHABLE; + return 0; // unreachable; +} + +bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0u; + else + return false; +} + +bool Value::operator!() const { return isNull(); } + +void Value::clear() { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || + type_ == objectValue, + "in Json::Value::clear(): requires complex value"); + start_ = 0; + limit_ = 0; + switch (type_) { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_->clear(); + break; +#else + case arrayValue: + value_.array_->clear(); + break; + case objectValue: + value_.map_->clear(); + break; +#endif + default: + break; + } +} + +void Value::resize(ArrayIndex newSize) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, + "in Json::Value::resize(): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ArrayIndex oldSize = size(); + if (newSize == 0) + clear(); + else if (newSize > oldSize) + (*this)[newSize - 1]; + else { + for (ArrayIndex index = newSize; index < oldSize; ++index) { + value_.map_->erase(index); + } + assert(size() == newSize); + } +#else + value_.array_->resize(newSize); +#endif +} + +Value& Value::operator[](ArrayIndex index) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString key(index); + ObjectValues::iterator it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) + return (*it).second; + + ObjectValues::value_type defaultValue(key, null); + it = value_.map_->insert(it, defaultValue); + return (*it).second; +#else + return value_.array_->resolveReference(index); +#endif +} + +Value& Value::operator[](int index) { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index): index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +const Value& Value::operator[](ArrayIndex index) const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); + if (type_ == nullValue) + return null; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString key(index); + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) + return null; + return (*it).second; +#else + Value* value = value_.array_->find(index); + return value ? *value : null; +#endif +} + +const Value& Value::operator[](int index) const { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index) const: index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +Value& Value::operator[](const char* key) { + return resolveReference(key, false); +} + +void Value::initBasic(ValueType type, bool allocated) { + type_ = type; + allocated_ = allocated; +#ifdef JSON_VALUE_USE_INTERNAL_MAP + itemIsUsed_ = 0; +#endif + comments_ = 0; + start_ = 0; + limit_ = 0; +} + +Value& Value::resolveReference(const char* key, bool isStatic) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey( + key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, null); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +#else + return value_.map_->resolveReference(key, isStatic); +#endif +} + +Value Value::get(ArrayIndex index, const Value& defaultValue) const { + const Value* value = &((*this)[index]); + return value == &null ? defaultValue : *value; +} + +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } + +const Value& Value::operator[](const char* key) const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::operator[](char const*)const: requires objectValue"); + if (type_ == nullValue) + return null; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey(key, CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return null; + return (*it).second; +#else + const Value* value = value_.map_->find(key); + return value ? *value : null; +#endif +} + +Value& Value::operator[](const std::string& key) { + return (*this)[key.c_str()]; +} + +const Value& Value::operator[](const std::string& key) const { + return (*this)[key.c_str()]; +} + +Value& Value::operator[](const StaticString& key) { + return resolveReference(key, true); +} + +#ifdef JSON_USE_CPPTL +Value& Value::operator[](const CppTL::ConstString& key) { + return (*this)[key.c_str()]; +} + +const Value& Value::operator[](const CppTL::ConstString& key) const { + return (*this)[key.c_str()]; +} +#endif + +Value& Value::append(const Value& value) { return (*this)[size()] = value; } + +Value Value::get(const char* key, const Value& defaultValue) const { + const Value* value = &((*this)[key]); + return value == &null ? defaultValue : *value; +} + +Value Value::get(const std::string& key, const Value& defaultValue) const { + return get(key.c_str(), defaultValue); +} + + +bool Value::removeMember(const char* key, Value* removed) { + if (type_ != objectValue) { + return false; + } +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey(key, CZString::noDuplication); + ObjectValues::iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return false; + *removed = it->second; + value_.map_->erase(it); + return true; +#else + Value* value = value_.map_->find(key); + if (value) { + *removed = *value; + value_.map_.remove(key); + return true; + } else { + return false; + } +#endif +} + +Value Value::removeMember(const char* key) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, + "in Json::Value::removeMember(): requires objectValue"); + if (type_ == nullValue) + return null; + + Value removed; // null + removeMember(key, &removed); + return removed; // still null if removeMember() did nothing +} + +Value Value::removeMember(const std::string& key) { + return removeMember(key.c_str()); +} + +bool Value::removeIndex(ArrayIndex index, Value* removed) { + if (type_ != arrayValue) { + return false; + } +#ifdef JSON_VALUE_USE_INTERNAL_MAP + JSON_FAIL_MESSAGE("removeIndex is not implemented for ValueInternalArray."); + return false; +#else + CZString key(index); + ObjectValues::iterator it = value_.map_->find(key); + if (it == value_.map_->end()) { + return false; + } + *removed = it->second; + ArrayIndex oldSize = size(); + // shift left all items left, into the place of the "removed" + for (ArrayIndex i = index; i < (oldSize - 1); ++i){ + CZString key(i); + (*value_.map_)[key] = (*this)[i + 1]; + } + // erase the last one ("leftover") + CZString keyLast(oldSize - 1); + ObjectValues::iterator itLast = value_.map_->find(keyLast); + value_.map_->erase(itLast); + return true; +#endif +} + +#ifdef JSON_USE_CPPTL +Value Value::get(const CppTL::ConstString& key, + const Value& defaultValue) const { + return get(key.c_str(), defaultValue); +} +#endif + +bool Value::isMember(const char* key) const { + const Value* value = &((*this)[key]); + return value != &null; +} + +bool Value::isMember(const std::string& key) const { + return isMember(key.c_str()); +} + +#ifdef JSON_USE_CPPTL +bool Value::isMember(const CppTL::ConstString& key) const { + return isMember(key.c_str()); +} +#endif + +Value::Members Value::getMemberNames() const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::getMemberNames(), value must be objectValue"); + if (type_ == nullValue) + return Value::Members(); + Members members; + members.reserve(value_.map_->size()); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for (; it != itEnd; ++it) + members.push_back(std::string((*it).first.c_str())); +#else + ValueInternalMap::IteratorState it; + ValueInternalMap::IteratorState itEnd; + value_.map_->makeBeginIterator(it); + value_.map_->makeEndIterator(itEnd); + for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it)) + members.push_back(std::string(ValueInternalMap::key(it))); +#endif + return members; +} +// +//# ifdef JSON_USE_CPPTL +// EnumMemberNames +// Value::enumMemberNames() const +//{ +// if ( type_ == objectValue ) +// { +// return CppTL::Enum::any( CppTL::Enum::transform( +// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), +// MemberNamesTransform() ) ); +// } +// return EnumMemberNames(); +//} +// +// +// EnumValues +// Value::enumValues() const +//{ +// if ( type_ == objectValue || type_ == arrayValue ) +// return CppTL::Enum::anyValues( *(value_.map_), +// CppTL::Type() ); +// return EnumValues(); +//} +// +//# endif + +static bool IsIntegral(double d) { + double integral_part; + return modf(d, &integral_part) == 0.0; +} + +bool Value::isNull() const { return type_ == nullValue; } + +bool Value::isBool() const { return type_ == booleanValue; } + +bool Value::isInt() const { + switch (type_) { + case intValue: + return value_.int_ >= minInt && value_.int_ <= maxInt; + case uintValue: + return value_.uint_ <= UInt(maxInt); + case realValue: + return value_.real_ >= minInt && value_.real_ <= maxInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isUInt() const { + switch (type_) { + case intValue: + return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); + case uintValue: + return value_.uint_ <= maxUInt; + case realValue: + return value_.real_ >= 0 && value_.real_ <= maxUInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return true; + case uintValue: + return value_.uint_ <= UInt64(maxInt64); + case realValue: + // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a + // double, so double(maxInt64) will be rounded up to 2^63. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < double(maxInt64) && IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isUInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return value_.int_ >= 0; + case uintValue: + return true; + case realValue: + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && + IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isIntegral() const { +#if defined(JSON_HAS_INT64) + return isInt64() || isUInt64(); +#else + return isInt() || isUInt(); +#endif +} + +bool Value::isDouble() const { return type_ == realValue || isIntegral(); } + +bool Value::isNumeric() const { return isIntegral() || isDouble(); } + +bool Value::isString() const { return type_ == stringValue; } + +bool Value::isArray() const { return type_ == arrayValue; } + +bool Value::isObject() const { return type_ == objectValue; } + +void Value::setComment(const char* comment, CommentPlacement placement) { + if (!comments_) + comments_ = new CommentInfo[numberOfCommentPlacement]; + comments_[placement].setComment(comment); +} + +void Value::setComment(const std::string& comment, CommentPlacement placement) { + setComment(comment.c_str(), placement); +} + +bool Value::hasComment(CommentPlacement placement) const { + return comments_ != 0 && comments_[placement].comment_ != 0; +} + +std::string Value::getComment(CommentPlacement placement) const { + if (hasComment(placement)) + return comments_[placement].comment_; + return ""; +} + +void Value::setOffsetStart(size_t start) { start_ = start; } + +void Value::setOffsetLimit(size_t limit) { limit_ = limit; } + +size_t Value::getOffsetStart() const { return start_; } + +size_t Value::getOffsetLimit() const { return limit_; } + +std::string Value::toStyledString() const { + StyledWriter writer; + return writer.write(*this); +} + +Value::const_iterator Value::begin() const { + switch (type_) { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeBeginIterator(it); + return const_iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeBeginIterator(it); + return const_iterator(it); + } + break; +#else + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; +#endif + default: + break; + } + return const_iterator(); +} + +Value::const_iterator Value::end() const { + switch (type_) { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeEndIterator(it); + return const_iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeEndIterator(it); + return const_iterator(it); + } + break; +#else + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; +#endif + default: + break; + } + return const_iterator(); +} + +Value::iterator Value::begin() { + switch (type_) { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeBeginIterator(it); + return iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeBeginIterator(it); + return iterator(it); + } + break; +#else + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; +#endif + default: + break; + } + return iterator(); +} + +Value::iterator Value::end() { + switch (type_) { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeEndIterator(it); + return iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeEndIterator(it); + return iterator(it); + } + break; +#else + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; +#endif + default: + break; + } + return iterator(); +} + +// class PathArgument +// ////////////////////////////////////////////////////////////////// + +PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} + +PathArgument::PathArgument(ArrayIndex index) + : key_(), index_(index), kind_(kindIndex) {} + +PathArgument::PathArgument(const char* key) + : key_(key), index_(), kind_(kindKey) {} + +PathArgument::PathArgument(const std::string& key) + : key_(key.c_str()), index_(), kind_(kindKey) {} + +// class Path +// ////////////////////////////////////////////////////////////////// + +Path::Path(const std::string& path, + const PathArgument& a1, + const PathArgument& a2, + const PathArgument& a3, + const PathArgument& a4, + const PathArgument& a5) { + InArgs in; + in.push_back(&a1); + in.push_back(&a2); + in.push_back(&a3); + in.push_back(&a4); + in.push_back(&a5); + makePath(path, in); +} + +void Path::makePath(const std::string& path, const InArgs& in) { + const char* current = path.c_str(); + const char* end = current + path.length(); + InArgs::const_iterator itInArg = in.begin(); + while (current != end) { + if (*current == '[') { + ++current; + if (*current == '%') + addPathInArg(path, in, itInArg, PathArgument::kindIndex); + else { + ArrayIndex index = 0; + for (; current != end && *current >= '0' && *current <= '9'; ++current) + index = index * 10 + ArrayIndex(*current - '0'); + args_.push_back(index); + } + if (current == end || *current++ != ']') + invalidPath(path, int(current - path.c_str())); + } else if (*current == '%') { + addPathInArg(path, in, itInArg, PathArgument::kindKey); + ++current; + } else if (*current == '.') { + ++current; + } else { + const char* beginName = current; + while (current != end && !strchr("[.", *current)) + ++current; + args_.push_back(std::string(beginName, current)); + } + } +} + +void Path::addPathInArg(const std::string& /*path*/, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind) { + if (itInArg == in.end()) { + // Error: missing argument %d + } else if ((*itInArg)->kind_ != kind) { + // Error: bad argument type + } else { + args_.push_back(**itInArg); + } +} + +void Path::invalidPath(const std::string& /*path*/, int /*location*/) { + // Error: invalid path. +} + +const Value& Path::resolve(const Value& root) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) { + // Error: unable to resolve path (array value expected at position... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: unable to resolve path (object value expected at position...) + } + node = &((*node)[arg.key_]); + if (node == &Value::null) { + // Error: unable to resolve path (object has no member named '' at + // position...) + } + } + } + return *node; +} + +Value Path::resolve(const Value& root, const Value& defaultValue) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) + return defaultValue; + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) + return defaultValue; + node = &((*node)[arg.key_]); + if (node == &Value::null) + return defaultValue; + } + } + return *node; +} + +Value& Path::make(Value& root) const { + Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray()) { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); + } + } + return *node; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below +#include +#define isfinite _finite +#define snprintf _snprintf +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +#if defined(__sun) && defined(__SVR4) //Solaris +#include +#define isfinite finite +#endif + +namespace Json { + +static bool containsControlCharacter(const char* str) { + while (*str) { + if (isControlCharacter(*(str++))) + return true; + } + return false; +} + +std::string valueToString(LargestInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + bool isNegative = value < 0; + if (isNegative) + value = -value; + uintToString(LargestUInt(value), current); + if (isNegative) + *--current = '-'; + assert(current >= buffer); + return current; +} + +std::string valueToString(LargestUInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + uintToString(value, current); + assert(current >= buffer); + return current; +} + +#if defined(JSON_HAS_INT64) + +std::string valueToString(Int value) { + return valueToString(LargestInt(value)); +} + +std::string valueToString(UInt value) { + return valueToString(LargestUInt(value)); +} + +#endif // # if defined(JSON_HAS_INT64) + +std::string valueToString(double value) { + // Allocate a buffer that is more than large enough to store the 16 digits of + // precision requested below. + char buffer[32]; + int len = -1; + +// Print into the buffer. We need not request the alternative representation +// that always has a decimal point because JSON doesn't distingish the +// concepts of reals and integers. +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with + // visual studio 2005 to + // avoid warning. +#if defined(WINCE) + len = _snprintf(buffer, sizeof(buffer), "%.17g", value); +#else + len = sprintf_s(buffer, sizeof(buffer), "%.17g", value); +#endif +#else + if (isfinite(value)) { + len = snprintf(buffer, sizeof(buffer), "%.17g", value); + } else { + // IEEE standard states that NaN values will not compare to themselves + if (value != value) { + len = snprintf(buffer, sizeof(buffer), "null"); + } else if (value < 0) { + len = snprintf(buffer, sizeof(buffer), "-1e+9999"); + } else { + len = snprintf(buffer, sizeof(buffer), "1e+9999"); + } + // For those, we do not need to call fixNumLoc, but it is fast. + } +#endif + assert(len >= 0); + fixNumericLocale(buffer, buffer + len); + return buffer; +} + +std::string valueToString(bool value) { return value ? "true" : "false"; } + +std::string valueToQuotedString(const char* value) { + if (value == NULL) + return ""; + // Not sure how to handle unicode... + if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && + !containsControlCharacter(value)) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + std::string::size_type maxsize = + strlen(value) * 2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + for (const char* c = value; *c != 0; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something. + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; + } + } + result += "\""; + return result; +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() {} + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), + omitEndingLineFeed_(false) {} + +void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } + +void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } + +void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } + +std::string FastWriter::write(const Value& root) { + document_ = ""; + writeValue(root); + if (!omitEndingLineFeed_) + document_ += "\n"; + return document_; +} + +void FastWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + if (!dropNullPlaceholders_) + document_ += "null"; + break; + case intValue: + document_ += valueToString(value.asLargestInt()); + break; + case uintValue: + document_ += valueToString(value.asLargestUInt()); + break; + case realValue: + document_ += valueToString(value.asDouble()); + break; + case stringValue: + document_ += valueToQuotedString(value.asCString()); + break; + case booleanValue: + document_ += valueToString(value.asBool()); + break; + case arrayValue: { + document_ += '['; + int size = value.size(); + for (int index = 0; index < size; ++index) { + if (index > 0) + document_ += ','; + writeValue(value[index]); + } + document_ += ']'; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += '{'; + for (Value::Members::iterator it = members.begin(); it != members.end(); + ++it) { + const std::string& name = *it; + if (it != members.begin()) + document_ += ','; + document_ += valueToQuotedString(name.c_str()); + document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + writeValue(value[name]); + } + document_ += '}'; + } break; + } +} + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() + : rightMargin_(74), indentSize_(3), addChildValues_() {} + +std::string StyledWriter::write(const Value& root) { + document_ = ""; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += "\n"; + return document_; +} + +void StyledWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + pushValue(valueToQuotedString(value.asCString())); + break; + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const std::string& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + document_ += "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + +bool StyledWriter::isMultineArray(const Value& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledWriter::pushValue(const std::string& value) { + if (addChildValues_) + childValues_.push_back(value); + else + document_ += value; +} + +void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; + if (last == ' ') // already indented + return; + if (last != '\n') // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + +void StyledWriter::writeWithIndent(const std::string& value) { + writeIndent(); + document_ += value; +} + +void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } + +void StyledWriter::unindent() { + assert(int(indentString_.size()) >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); +} + +void StyledWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + document_ += "\n"; + writeIndent(); + const std::string& comment = root.getComment(commentBefore); + std::string::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + document_ += *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) + writeIndent(); + ++iter; + } + + // Comments are stripped of trailing newlines, so add one here + document_ += "\n"; +} + +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + document_ += " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + document_ += "\n"; + document_ += root.getComment(commentAfter); + document_ += "\n"; + } +} + +bool StyledWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter(std::string indentation) + : document_(NULL), rightMargin_(74), indentation_(indentation), + addChildValues_() {} + +void StyledStreamWriter::write(std::ostream& out, const Value& root) { + document_ = &out; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + +void StyledStreamWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + pushValue(valueToQuotedString(value.asCString())); + break; + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const std::string& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledStreamWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *document_ << "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + +bool StyledStreamWriter::isMultineArray(const Value& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledStreamWriter::pushValue(const std::string& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *document_ << value; +} + +void StyledStreamWriter::writeIndent() { + /* + Some comments in this method would have been nice. ;-) + + if ( !document_.empty() ) + { + char last = document_[document_.length()-1]; + if ( last == ' ' ) // already indented + return; + if ( last != '\n' ) // Comments may add new-line + *document_ << '\n'; + } + */ + *document_ << '\n' << indentString_; +} + +void StyledStreamWriter::writeWithIndent(const std::string& value) { + writeIndent(); + *document_ << value; +} + +void StyledStreamWriter::indent() { indentString_ += indentation_; } + +void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + *document_ << root.getComment(commentBefore); + *document_ << "\n"; +} + +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + *document_ << " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + *document_ << "\n"; + *document_ << root.getComment(commentAfter); + *document_ << "\n"; + } +} + +bool StyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +std::ostream& operator<<(std::ostream& sout, const Value& root) { + Json::StyledStreamWriter writer; + writer.write(sout, root); + return sout; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + + + + +