Merge pull request #535 from syoyo/copilot/optimize-json-parser

Add tinygltf_json.h: fast custom JSON parser with optional SIMD acceleration
This commit is contained in:
Syoyo Fujita
2026-03-19 09:29:56 +09:00
committed by GitHub
4 changed files with 1954 additions and 2 deletions

13
.gitignore vendored
View File

@@ -70,6 +70,19 @@ tests/tester
tests/tester_noexcept
tests/issue-97.gltf
tests/issue-261.gltf
tests/issue-495-external.gltf
# Test-generated output files (written by tester.cc during test run)
tests/Cube.gltf
tests/Cube.bin
tests/Cube.glb
tests/Cube_BaseColor.png
tests/Cube_MetallicRoughness.png
tests/Cube_with_embedded_images.gltf
tests/Cube_with_image_files.gltf
tests/tmp.glb
tests/ issue-236.gltf
tests/ issue-236.bin
tests/ 2x2 image has multiple spaces.png
# unignore
!Makefile

View File

@@ -18,6 +18,7 @@ option(TINYGLTF_BUILD_TESTS "Build unit tests" OFF)
option(TINYGLTF_HEADER_ONLY "On: header-only mode. Off: create tinygltf library(No TINYGLTF_IMPLEMENTATION required in your project)" OFF)
option(TINYGLTF_INSTALL "Install tinygltf files during install step. Usually set to OFF if you include tinygltf through add_subdirectory()" ON)
option(TINYGLTF_INSTALL_VENDOR "Install vendored nlohmann/json and nothings/stb headers" ON)
option(TINYGLTF_USE_CUSTOM_JSON "Use the built-in fast JSON parser (tinygltf_json.h) instead of nlohmann/json" OFF)
if (TINYGLTF_BUILD_LOADER_EXAMPLE)
add_executable(loader_example
@@ -46,6 +47,15 @@ if (TINYGLTF_BUILD_TESTS)
${CMAKE_CURRENT_SOURCE_DIR}/tests
)
add_test(NAME tester COMMAND tester WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
# Build and run tests with the custom JSON backend enabled to catch regressions
add_executable(tester_customjson tests/tester.cc)
target_include_directories(tester_customjson PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/tests
)
target_compile_definitions(tester_customjson PRIVATE TINYGLTF_USE_CUSTOM_JSON)
add_test(NAME tester_customjson COMMAND tester_customjson WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
endif (TINYGLTF_BUILD_TESTS)
#
@@ -71,6 +81,14 @@ else (TINYGLTF_HEADER_ONLY)
)
endif (TINYGLTF_HEADER_ONLY)
if (TINYGLTF_USE_CUSTOM_JSON)
if (TINYGLTF_HEADER_ONLY)
target_compile_definitions(tinygltf INTERFACE TINYGLTF_USE_CUSTOM_JSON)
else ()
target_compile_definitions(tinygltf PUBLIC TINYGLTF_USE_CUSTOM_JSON)
endif ()
endif ()
if (TINYGLTF_INSTALL)
install(TARGETS tinygltf EXPORT tinygltfTargets)
install(EXPORT tinygltfTargets NAMESPACE tinygltf:: FILE TinyGLTFTargets.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/tinygltf)
@@ -80,6 +98,7 @@ if (TINYGLTF_INSTALL)
INSTALL ( FILES
tiny_gltf.h
tinygltf_json.h
${TINYGLTF_EXTRA_SOUECES}
DESTINATION
include

View File

@@ -1711,7 +1711,11 @@ class TinyGLTF {
#endif // __GNUC__
#ifndef TINYGLTF_NO_INCLUDE_JSON
#ifndef TINYGLTF_USE_RAPIDJSON
#ifdef TINYGLTF_USE_CUSTOM_JSON
#ifndef TINYGLTF_NO_INCLUDE_CUSTOM_JSON
#include "tinygltf_json.h"
#endif
#elif !defined(TINYGLTF_USE_RAPIDJSON)
#include "json.hpp"
#else
#ifndef TINYGLTF_NO_INCLUDE_RAPIDJSON
@@ -1799,7 +1803,10 @@ class TinyGLTF {
namespace tinygltf {
namespace detail {
#ifdef TINYGLTF_USE_RAPIDJSON
#ifdef TINYGLTF_USE_CUSTOM_JSON
// Types and JsonParse are provided by tinygltf_json.h (already included above)
// via 'namespace tinygltf { namespace detail { ... } }' declarations.
#elif defined(TINYGLTF_USE_RAPIDJSON)
#ifdef TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
// This uses the RapidJSON CRTAllocator. It is thread safe and multiple
@@ -1871,6 +1878,7 @@ using json_const_array_iterator = json_const_iterator;
using JsonDocument = json;
#endif
#ifndef TINYGLTF_USE_CUSTOM_JSON
void JsonParse(JsonDocument &doc, const char *str, size_t length,
bool throwExc = false) {
#ifdef TINYGLTF_USE_RAPIDJSON
@@ -1880,6 +1888,7 @@ void JsonParse(JsonDocument &doc, const char *str, size_t length,
doc = detail::json::parse(str, str + length, nullptr, throwExc);
#endif
}
#endif // !TINYGLTF_USE_CUSTOM_JSON
} // namespace detail
} // namespace tinygltf
@@ -3436,6 +3445,7 @@ bool DecodeDataURI(std::vector<unsigned char> *out, std::string &mime_type,
return true;
}
#ifndef TINYGLTF_USE_CUSTOM_JSON
namespace detail {
bool GetInt(const detail::json &o, int &val) {
#ifdef TINYGLTF_USE_RAPIDJSON
@@ -3659,6 +3669,7 @@ std::string JsonToString(const detail::json &o, int spacing = -1) {
}
} // namespace detail
#endif // !TINYGLTF_USE_CUSTOM_JSON
static bool ParseJsonAsValue(Value *ret, const detail::json &o) {
Value val{};
@@ -6962,6 +6973,7 @@ bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
///////////////////////
// GLTF Serialization
///////////////////////
#ifndef TINYGLTF_USE_CUSTOM_JSON
namespace detail {
detail::json JsonFromString(const char *s) {
#ifdef TINYGLTF_USE_RAPIDJSON
@@ -7034,6 +7046,7 @@ void JsonReserveArray(detail::json &o, size_t s) {
(void)(s);
}
} // namespace detail
#endif // !TINYGLTF_USE_CUSTOM_JSON
// typedef std::pair<std::string, detail::json> json_object_pair;

1907
tinygltf_json.h Normal file

File diff suppressed because it is too large Load Diff