mirror of
https://github.com/syoyo/tinygltf.git
synced 2026-06-08 03:03:50 +00:00
Compare commits
6 Commits
d31c16e333
...
fd365dddab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd365dddab | ||
|
|
a4b5752b1b | ||
|
|
2ff44b903c | ||
|
|
381daedaba | ||
|
|
34a166cdac | ||
|
|
0e3043f3e9 |
92
.github/instructions/copilot-instructions.md
vendored
92
.github/instructions/copilot-instructions.md
vendored
@@ -1,92 +0,0 @@
|
||||
# Copilot Review Instructions for TinyGLTF
|
||||
|
||||
This document provides guidelines for reviewing code changes in the TinyGLTF repository.
|
||||
|
||||
## Memory Safety
|
||||
|
||||
- **Buffer Overflows**: Check for proper bounds checking when accessing arrays, vectors, and buffers. Verify that buffer sizes are validated before read/write operations.
|
||||
- **Null Pointer Dereferences**: Ensure all pointers are checked for null before dereferencing, especially when handling optional glTF fields.
|
||||
- **Memory Leaks**: Verify proper resource management, including RAII patterns for file handles, image data, and dynamically allocated memory.
|
||||
- **Use-After-Free**: Check for proper lifetime management of objects, especially when dealing with callbacks and asynchronous operations.
|
||||
|
||||
## Error Handling
|
||||
|
||||
- **File I/O**: Verify that all file operations have proper error checking and meaningful error messages.
|
||||
- **JSON Parsing**: Ensure JSON parsing errors are caught and reported with helpful context about the location and nature of the error.
|
||||
- **Resource Loading**: Check that failures in loading images, buffers, and other resources are properly handled and don't cause crashes.
|
||||
- **Error Propagation**: Verify that errors are properly propagated through the call stack with appropriate error messages.
|
||||
|
||||
## glTF 2.0 Specification Compliance
|
||||
|
||||
- **Required Fields**: Ensure all required glTF fields are validated and present.
|
||||
- **Data Types**: Verify that data types match the glTF specification (e.g., component types, accessor types).
|
||||
- **Constraints**: Check that glTF constraints are enforced (e.g., valid ranges for enums, buffer stride requirements).
|
||||
- **Extensions**: Verify proper handling of glTF extensions and that unknown extensions are handled gracefully.
|
||||
- **Validation**: Ensure new features align with the glTF 2.0 specification from the Khronos Group.
|
||||
|
||||
## Cross-Platform Compatibility
|
||||
|
||||
- **Windows**: Check for proper handling of Windows-specific issues (path separators, line endings, file operations).
|
||||
- **Linux**: Verify compatibility with various Linux distributions and compilers (GCC, Clang).
|
||||
- **macOS**: Ensure macOS-specific considerations are addressed (case-sensitive filesystems, Clang compatibility).
|
||||
- **Mobile Platforms**: Consider Android and iOS compatibility where applicable.
|
||||
- **Endianness**: Verify proper handling of byte order when reading binary data.
|
||||
- **Compiler Compatibility**: Ensure code compiles with C++11 standard and supported compilers (MSVC, GCC, Clang).
|
||||
|
||||
## Edge Cases in glTF Parsing
|
||||
|
||||
- **Empty/Minimal Files**: Verify handling of minimal valid glTF files.
|
||||
- **Large Files**: Check for proper handling of large glTF files and buffers without memory exhaustion.
|
||||
- **Malformed Data**: Ensure graceful handling of malformed or invalid glTF data.
|
||||
- **Missing Optional Fields**: Verify correct behavior when optional glTF fields are absent.
|
||||
- **Edge Values**: Check handling of boundary values (e.g., maximum buffer sizes, extreme floating-point values).
|
||||
- **Base64 Encoding**: Verify proper handling of base64-encoded data URIs and invalid encodings.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
- **API Changes**: Ensure public API changes maintain backwards compatibility or are properly deprecated.
|
||||
- **Breaking Changes**: Flag any breaking changes for major version updates and document migration paths.
|
||||
- **Binary Compatibility**: Consider ABI stability for header-only library changes.
|
||||
- **Default Behavior**: Verify that default behavior of existing functionality remains unchanged.
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- **Parsing Performance**: Check for unnecessary copies, redundant allocations, and inefficient algorithms in parsing logic.
|
||||
- **Memory Usage**: Verify efficient memory usage, especially when loading large glTF files.
|
||||
- **I/O Operations**: Ensure efficient file reading and minimize unnecessary disk access.
|
||||
- **String Operations**: Check for efficient string handling (use of string_view, move semantics).
|
||||
- **STL Usage**: Verify appropriate use of STL containers and algorithms.
|
||||
|
||||
## Documentation
|
||||
|
||||
- **Public API**: Ensure all public functions, classes, and methods have clear documentation comments.
|
||||
- **Parameters**: Verify that function parameters are documented, including expected ranges and constraints.
|
||||
- **Return Values**: Document return values and possible error conditions.
|
||||
- **Examples**: Check that complex features include usage examples.
|
||||
- **Changelog**: Verify that significant changes are documented in release notes or changelog.
|
||||
|
||||
## Testing
|
||||
|
||||
- **Test Coverage**: Ensure new features include appropriate unit tests or integration tests.
|
||||
- **Edge Cases**: Verify that tests cover edge cases and error conditions.
|
||||
- **Cross-Platform Tests**: Check that tests run on all supported platforms.
|
||||
- **Regression Tests**: Ensure bug fixes include regression tests to prevent recurrence.
|
||||
- **Sample Files**: Verify that changes are tested with various valid and invalid glTF sample files.
|
||||
|
||||
## Code Style Consistency
|
||||
|
||||
- **Header-Only Pattern**: Maintain the header-only library structure.
|
||||
- **Naming Conventions**: Follow existing naming conventions (CamelCase for types, snake_case for functions where applicable).
|
||||
- **Formatting**: Adhere to the existing code formatting style (check `.clang-format` if available).
|
||||
- **Include Guards**: Verify proper include guards and header organization.
|
||||
- **Namespace Usage**: Ensure proper use of the `tinygltf` namespace.
|
||||
- **Comments**: Maintain consistent comment style with existing code.
|
||||
- **C++11 Compliance**: Verify that code uses C++11 features appropriately and doesn't require newer standards unless specified.
|
||||
|
||||
## Additional Considerations
|
||||
|
||||
- **Third-Party Dependencies**: Minimize new dependencies; prefer existing dependencies (json.hpp, stb_image).
|
||||
- **Warnings**: Ensure code compiles without warnings on supported compilers.
|
||||
- **const Correctness**: Verify proper use of const for parameters and methods.
|
||||
- **RAII**: Prefer RAII patterns for resource management over manual cleanup.
|
||||
- **noexcept**: Use noexcept appropriately for move constructors and move assignment operators.
|
||||
11
.github/workflows/c-cpp.yml
vendored
11
.github/workflows/c-cpp.yml
vendored
@@ -66,10 +66,12 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake --help
|
||||
cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On ..
|
||||
cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=On -DTINYGLTF_BUILD_TESTS=ON ..
|
||||
cd ..
|
||||
- name: Build
|
||||
run: cmake --build build --config Release
|
||||
- name: Run tests
|
||||
run: ctest --test-dir build -C Release --output-on-failure
|
||||
|
||||
|
||||
build-linux:
|
||||
@@ -109,6 +111,12 @@ jobs:
|
||||
cc -I../ -std=c11 -g -O0 -DTINYGLTF3_ENABLE_FS \
|
||||
-o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c
|
||||
./tester_v3_c_v1port
|
||||
cc -I../ -std=c11 -g -O0 \
|
||||
-o tester_v3_json_c tester_v3_json_c.c
|
||||
./tester_v3_json_c
|
||||
cc -I../ -std=c11 -ffreestanding -g -O0 \
|
||||
-o tester_v3_freestanding tester_v3_freestanding.c
|
||||
./tester_v3_freestanding
|
||||
cd ..
|
||||
|
||||
|
||||
@@ -177,4 +185,3 @@ jobs:
|
||||
|
||||
git clone https://github.com/Tencent/rapidjson
|
||||
clang++ -DTINYGLTF_USE_RAPIDJSON -I./rapidjson/include/rapidjson -std=c++11 -g -O0 -o loader_example loader_example.cc
|
||||
|
||||
|
||||
42
.github/workflows/ci.yml
vendored
42
.github/workflows/ci.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Configure
|
||||
run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON
|
||||
run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -B build -DCMAKE_C_COMPILER=clang-21 -DCMAKE_CXX_COMPILER=clang++-21 -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON
|
||||
cmake -B build -DCMAKE_C_COMPILER=clang-21 -DCMAKE_CXX_COMPILER=clang++-21 -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Configure
|
||||
run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON
|
||||
run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Configure
|
||||
run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON
|
||||
run: cmake -B build -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=Off ..
|
||||
cmake -G "Visual Studio 17 2022" -A x64 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=Off -DTINYGLTF_BUILD_TESTS=ON ..
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build --config Release
|
||||
@@ -141,7 +141,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "Visual Studio 17 2022" -A Win32 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=Off ..
|
||||
cmake -G "Visual Studio 17 2022" -A Win32 -DTINYGLTF_BUILD_LOADER_EXAMPLE=On -DTINYGLTF_BUILD_GL_EXAMPLES=Off -DTINYGLTF_BUILD_VALIDATOR_EXAMPLE=Off -DTINYGLTF_BUILD_TESTS=ON ..
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build --config Release
|
||||
@@ -189,7 +189,7 @@ jobs:
|
||||
|
||||
- name: Build with CMake
|
||||
run: |
|
||||
cmake -G"Ninja" -S . -B build
|
||||
cmake -G"Ninja" -S . -B build -DTINYGLTF_BUILD_TESTS=ON
|
||||
cmake --build build
|
||||
|
||||
- name: Run loader_example
|
||||
@@ -249,7 +249,7 @@ jobs:
|
||||
- name: Build with CMake Header-Only
|
||||
run: |
|
||||
mkdir build
|
||||
cmake -B build -DTINYGLTF_HEADER_ONLY=ON -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON
|
||||
cmake -B build -DTINYGLTF_HEADER_ONLY=ON -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON
|
||||
cmake --build build
|
||||
|
||||
- name: Run loader_example
|
||||
@@ -259,6 +259,30 @@ jobs:
|
||||
- name: Run tests
|
||||
run: ctest --test-dir build --output-on-failure
|
||||
|
||||
# v3 C tests through Meson on the primary desktop platforms.
|
||||
v3-c-meson:
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: v3 C Meson (${{ matrix.os }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Meson
|
||||
run: python -m pip install meson ninja
|
||||
|
||||
- name: Configure
|
||||
run: meson setup build-meson -Dtests=true
|
||||
|
||||
- name: Build
|
||||
run: meson compile -C build-meson
|
||||
|
||||
- name: Run v3 C tests
|
||||
run: meson test -C build-meson --print-errorlogs
|
||||
|
||||
# Special Configuration: RapidJSON Backend
|
||||
linux-rapidjson:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -273,7 +297,7 @@ jobs:
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -B build -DTINYGLTF_USE_RAPIDJSON=ON -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DCMAKE_PREFIX_PATH=$PWD/rapidjson
|
||||
cmake -B build -DTINYGLTF_USE_RAPIDJSON=ON -DTINYGLTF_BUILD_LOADER_EXAMPLE=ON -DTINYGLTF_BUILD_TESTS=ON -DCMAKE_PREFIX_PATH=$PWD/rapidjson
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
|
||||
72
.github/workflows/codeql-analysis.yml
vendored
72
.github/workflows/codeql-analysis.yml
vendored
@@ -1,72 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '21 20 * * 5'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp', 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
10
.github/workflows/mingw-w64-msys2.yml
vendored
10
.github/workflows/mingw-w64-msys2.yml
vendored
@@ -7,7 +7,11 @@ on:
|
||||
- devel
|
||||
paths:
|
||||
- 'tiny_gltf.*'
|
||||
- 'tinygltf_json_c.h'
|
||||
- 'CMakeLists.txt'
|
||||
- 'meson.build'
|
||||
- 'meson_options.txt'
|
||||
- 'tests/tester_v3*.c'
|
||||
- '.github/workflows/mingw-w64-msys2.yml'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
@@ -37,9 +41,13 @@ jobs:
|
||||
cmake \
|
||||
-G"Ninja" \
|
||||
-S . \
|
||||
-B build
|
||||
-B build \
|
||||
-DTINYGLTF_BUILD_TESTS=ON
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
ctest --test-dir build --output-on-failure
|
||||
|
||||
@@ -41,6 +41,21 @@ endif (TINYGLTF_BUILD_BUILDER_EXAMPLE)
|
||||
|
||||
if (TINYGLTF_BUILD_TESTS)
|
||||
enable_testing()
|
||||
|
||||
function(add_tinygltf_v3_c_test target)
|
||||
add_executable(${target} ${ARGN})
|
||||
target_include_directories(${target} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests
|
||||
)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
C_STANDARD 11
|
||||
C_STANDARD_REQUIRED ON
|
||||
C_EXTENSIONS OFF
|
||||
)
|
||||
add_test(NAME ${target} COMMAND ${target} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
|
||||
endfunction()
|
||||
|
||||
add_executable(tester tests/tester.cc)
|
||||
target_include_directories(tester PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
@@ -66,20 +81,18 @@ if (TINYGLTF_BUILD_TESTS)
|
||||
target_compile_definitions(tester_intensive_customjson PRIVATE TINYGLTF_USE_CUSTOM_JSON)
|
||||
add_test(NAME tester_intensive_customjson COMMAND tester_intensive_customjson WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
|
||||
|
||||
add_executable(tester_v3_c
|
||||
tests/tester_v3_c.c
|
||||
tiny_gltf_v3.c
|
||||
)
|
||||
target_include_directories(tester_v3_c PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests
|
||||
)
|
||||
set_target_properties(tester_v3_c PROPERTIES
|
||||
C_STANDARD 11
|
||||
C_STANDARD_REQUIRED ON
|
||||
C_EXTENSIONS OFF
|
||||
)
|
||||
add_test(NAME tester_v3_c COMMAND tester_v3_c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
|
||||
add_tinygltf_v3_c_test(tester_v3_c tests/tester_v3_c.c tiny_gltf_v3.c)
|
||||
target_compile_definitions(tester_v3_c PRIVATE TINYGLTF3_ENABLE_FS)
|
||||
|
||||
add_tinygltf_v3_c_test(tester_v3_c_v1port tests/tester_v3_c_v1port.c tiny_gltf_v3.c)
|
||||
target_compile_definitions(tester_v3_c_v1port PRIVATE TINYGLTF3_ENABLE_FS)
|
||||
|
||||
add_tinygltf_v3_c_test(tester_v3_json_c tests/tester_v3_json_c.c)
|
||||
|
||||
add_tinygltf_v3_c_test(tester_v3_freestanding tests/tester_v3_freestanding.c)
|
||||
if (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
|
||||
target_compile_options(tester_v3_freestanding PRIVATE -ffreestanding)
|
||||
endif()
|
||||
endif (TINYGLTF_BUILD_TESTS)
|
||||
|
||||
#
|
||||
|
||||
@@ -61,8 +61,10 @@ The v3 C runtime is built for processing **untrusted glTF/GLB input** (server-si
|
||||
|
||||
- **URI sanitization** — external buffer/image URIs are rejected before any filesystem call if they are empty, contain NUL bytes, begin with `/` or `\`, look like a Windows drive prefix (`X:`), or contain a `..` segment. Production callers SHOULD still provide a custom `tg3_fs_callbacks.read_file` that confines reads to a known directory (e.g. via `openat` plus a `realpath` prefix check) when the input is attacker-controlled.
|
||||
- **Index bounds validation** — every `int32_t` index field populated from JSON (accessor.bufferView, primitive.indices/material/attributes, scene.nodes[], skin.joints[], animation channel/sampler refs, KHR_audio + MSFT_lod refs, …) is checked after the structural parse. Out-of-range indices produce `TG3_ERR_INVALID_INDEX`. Default `tg3_parse_options.validate_indices = 1`; set to `0` only when you need raw round-trip and have your own validator.
|
||||
- **Buffer/accessor range validation** — declared buffer lengths, bufferView ranges, accessor element spans, sparse accessor spans, component types, and overflow-prone size math are checked before returning a model.
|
||||
- **Strict numeric range checks** — JSON numbers feeding integer fields go through finite/round-trip-validated coercion (`tg3__json_number_to_int32` / `_uint64`). `byteStride` is restricted to 0 or [4, 252].
|
||||
- **Memory budget** — the arena is capped at `TINYGLTF3_MAX_MEMORY_BYTES` (1 GB by default; configurable via `tg3_memory_config`).
|
||||
- **Memory budget** — the arena and C JSON parser enforce `TINYGLTF3_MAX_MEMORY_BYTES` by default; `max_single_alloc` and `TINYGLTF3_MAX_STRING_LENGTH` bound individual allocation and string size.
|
||||
- **Opt-in fast paths** — `skip_extras_values` avoids materializing `extras` and unknown extension value trees, and `borrow_input_buffers` lets GLB buffer spans reference caller-owned input bytes instead of copying the BIN chunk.
|
||||
- **Image decoding off by default** — the parser does not decode image bytes; use `tg3_parse_options.images_as_is = 1` to skip any decoder entirely when handling untrusted input.
|
||||
- **Error message lifetime** — error strings on `tg3_error_stack` are arena-allocated and remain valid until `tg3_model_free()`. Read or copy them BEFORE freeing the model.
|
||||
|
||||
|
||||
@@ -139,7 +139,9 @@ struct BenchResult {
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static BenchResult bench_file(const char *filename, int iterations, int warmup,
|
||||
bool quiet, int float32_mode = 0) {
|
||||
bool quiet, int float32_mode = 0,
|
||||
int skip_extras_values = 0,
|
||||
int borrow_input_buffers = 0) {
|
||||
BenchResult r = {};
|
||||
r.filename = filename;
|
||||
r.iterations = iterations;
|
||||
@@ -199,6 +201,8 @@ static BenchResult bench_file(const char *filename, int iterations, int warmup,
|
||||
opts.memory.allocator.free = tracked_free;
|
||||
opts.memory.allocator.user_data = &tracker;
|
||||
opts.parse_float32 = float32_mode;
|
||||
opts.skip_extras_values = skip_extras_values;
|
||||
opts.borrow_input_buffers = borrow_input_buffers;
|
||||
|
||||
tg3_model model;
|
||||
tg3_error_stack errors;
|
||||
@@ -340,7 +344,11 @@ static void usage() {
|
||||
" --csv Output in CSV format\n"
|
||||
" --quiet Suppress per-iteration error messages\n"
|
||||
" --batch Benchmark multiple files\n"
|
||||
" --float32 Parse JSON floats as float32 (faster, less precise)\n");
|
||||
" --float32 Parse JSON floats as float32 (faster, less precise)\n"
|
||||
" --skip-extras-values\n"
|
||||
" Skip materializing extras/unknown extension values\n"
|
||||
" --borrow-input-buffers\n"
|
||||
" Let GLB buffers reference caller-owned input bytes\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
@@ -351,6 +359,8 @@ int main(int argc, char **argv) {
|
||||
bool csv = false;
|
||||
bool quiet = false;
|
||||
int float32_mode = 0;
|
||||
int skip_extras_values = 0;
|
||||
int borrow_input_buffers = 0;
|
||||
std::vector<std::string> files;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
@@ -364,6 +374,10 @@ int main(int argc, char **argv) {
|
||||
quiet = true;
|
||||
} else if (strcmp(argv[i], "--float32") == 0) {
|
||||
float32_mode = 1;
|
||||
} else if (strcmp(argv[i], "--skip-extras-values") == 0) {
|
||||
skip_extras_values = 1;
|
||||
} else if (strcmp(argv[i], "--borrow-input-buffers") == 0) {
|
||||
borrow_input_buffers = 1;
|
||||
} else if (strcmp(argv[i], "--batch") == 0) {
|
||||
/* batch mode: just collect files */
|
||||
} else if (argv[i][0] != '-') {
|
||||
@@ -379,10 +393,14 @@ int main(int argc, char **argv) {
|
||||
if (!csv && !quiet) {
|
||||
printf("Benchmarking: %s (%d iterations, %d warmup%s)\n",
|
||||
file.c_str(), iterations, warmup,
|
||||
float32_mode ? ", float32" : "");
|
||||
float32_mode ? ", float32" :
|
||||
skip_extras_values ? ", skip extras" :
|
||||
borrow_input_buffers ? ", borrow buffers" : "");
|
||||
}
|
||||
|
||||
BenchResult r = bench_file(file.c_str(), iterations, warmup, quiet, float32_mode);
|
||||
BenchResult r = bench_file(file.c_str(), iterations, warmup, quiet,
|
||||
float32_mode, skip_extras_values,
|
||||
borrow_input_buffers);
|
||||
|
||||
if (csv) {
|
||||
print_csv_row(r);
|
||||
|
||||
52
meson.build
Normal file
52
meson.build
Normal file
@@ -0,0 +1,52 @@
|
||||
project(
|
||||
'tinygltf',
|
||||
'c',
|
||||
default_options: ['c_std=c11'],
|
||||
meson_version: '>=0.55.0',
|
||||
)
|
||||
|
||||
tinygltf_inc = include_directories('.', 'tests')
|
||||
|
||||
if get_option('tests')
|
||||
tests_workdir = join_paths(meson.current_source_dir(), 'tests')
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
tester_v3_c = executable(
|
||||
'tester_v3_c',
|
||||
['tests/tester_v3_c.c', 'tiny_gltf_v3.c'],
|
||||
include_directories: tinygltf_inc,
|
||||
c_args: ['-DTINYGLTF3_ENABLE_FS'],
|
||||
install: false,
|
||||
)
|
||||
test('tester_v3_c', tester_v3_c, workdir: tests_workdir)
|
||||
|
||||
tester_v3_c_v1port = executable(
|
||||
'tester_v3_c_v1port',
|
||||
['tests/tester_v3_c_v1port.c', 'tiny_gltf_v3.c'],
|
||||
include_directories: tinygltf_inc,
|
||||
c_args: ['-DTINYGLTF3_ENABLE_FS'],
|
||||
install: false,
|
||||
)
|
||||
test('tester_v3_c_v1port', tester_v3_c_v1port, workdir: tests_workdir)
|
||||
|
||||
tester_v3_json_c = executable(
|
||||
'tester_v3_json_c',
|
||||
'tests/tester_v3_json_c.c',
|
||||
include_directories: tinygltf_inc,
|
||||
install: false,
|
||||
)
|
||||
test('tester_v3_json_c', tester_v3_json_c, workdir: tests_workdir)
|
||||
|
||||
freestanding_args = []
|
||||
if cc.get_id() in ['clang', 'gcc']
|
||||
freestanding_args += ['-ffreestanding']
|
||||
endif
|
||||
tester_v3_freestanding = executable(
|
||||
'tester_v3_freestanding',
|
||||
'tests/tester_v3_freestanding.c',
|
||||
include_directories: tinygltf_inc,
|
||||
c_args: freestanding_args,
|
||||
install: false,
|
||||
)
|
||||
test('tester_v3_freestanding', tester_v3_freestanding, workdir: tests_workdir)
|
||||
endif
|
||||
1
meson_options.txt
Normal file
1
meson_options.txt
Normal file
@@ -0,0 +1 @@
|
||||
option('tests', type: 'boolean', value: true, description: 'Build and run tinygltf tests')
|
||||
@@ -1,7 +1,7 @@
|
||||
# Use this for strict compilation check(will work on clang 3.8+)
|
||||
#EXTRA_CXXFLAGS := -fsanitize=address -Wall -Werror -Weverything -Wno-c++11-long-long -DTINYGLTF_APPLY_CLANG_WEVERYTHING
|
||||
|
||||
all: ../tiny_gltf.h tester_v3_c tester_v3_c_v1port
|
||||
all: ../tiny_gltf.h tester_v3_c tester_v3_c_v1port tester_v3_json_c tester_v3_freestanding
|
||||
clang++ -I../ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o tester tester.cc
|
||||
clang++ -DTINYGLTF_NOEXCEPTION -I../ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o tester_noexcept tester.cc
|
||||
clang++ -DTINYGLTF_USE_CUSTOM_JSON -I../ $(EXTRA_CXXFLAGS) -std=c++11 -g -O0 -o tester_intensive_customjson tester_intensive_customjson.cc
|
||||
@@ -11,3 +11,9 @@ tester_v3_c: tester_v3_c.c ../tiny_gltf_v3.h ../tiny_gltf_v3.c ../tinygltf_json_
|
||||
|
||||
tester_v3_c_v1port: tester_v3_c_v1port.c ../tiny_gltf_v3.h ../tiny_gltf_v3.c ../tinygltf_json_c.h
|
||||
clang -I../ -std=c11 -g -O0 -DTINYGLTF3_ENABLE_FS -o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c
|
||||
|
||||
tester_v3_json_c: tester_v3_json_c.c ../tinygltf_json_c.h
|
||||
clang -I../ -std=c11 -g -O0 -o tester_v3_json_c tester_v3_json_c.c
|
||||
|
||||
tester_v3_freestanding: tester_v3_freestanding.c ../tiny_gltf_v3.h ../tiny_gltf_v3.c ../tinygltf_json_c.h
|
||||
clang -I../ -std=c11 -ffreestanding -g -O0 -o tester_v3_freestanding tester_v3_freestanding.c
|
||||
|
||||
1029
tests/tester_v3_c.c
1029
tests/tester_v3_c.c
File diff suppressed because it is too large
Load Diff
75
tests/tester_v3_freestanding.c
Normal file
75
tests/tester_v3_freestanding.c
Normal file
@@ -0,0 +1,75 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static union {
|
||||
uint64_t align;
|
||||
unsigned char bytes[512 * 1024];
|
||||
} test_heap;
|
||||
static size_t test_heap_used;
|
||||
|
||||
static void *test_malloc(size_t size) {
|
||||
size_t total = (size + sizeof(size_t) + 7u) & ~(size_t)7u;
|
||||
if (test_heap_used + total > sizeof(test_heap.bytes)) return 0;
|
||||
{
|
||||
unsigned char *base = test_heap.bytes + test_heap_used;
|
||||
*((size_t *)base) = size;
|
||||
test_heap_used += total;
|
||||
return base + sizeof(size_t);
|
||||
}
|
||||
}
|
||||
|
||||
static void *test_realloc(void *ptr, size_t size) {
|
||||
unsigned char *old_base;
|
||||
size_t old_size;
|
||||
unsigned char *new_ptr;
|
||||
size_t n;
|
||||
size_t i;
|
||||
if (!ptr) return test_malloc(size);
|
||||
old_base = (unsigned char *)ptr - sizeof(size_t);
|
||||
old_size = *((size_t *)old_base);
|
||||
new_ptr = (unsigned char *)test_malloc(size);
|
||||
if (!new_ptr) return 0;
|
||||
n = old_size < size ? old_size : size;
|
||||
for (i = 0; i < n; ++i) new_ptr[i] = ((unsigned char *)ptr)[i];
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
static void test_free(void *ptr) {
|
||||
(void)ptr;
|
||||
}
|
||||
|
||||
#define TINYGLTF3_NO_STDLIB
|
||||
#define TINYGLTF3_MALLOC(sz) test_malloc(sz)
|
||||
#define TINYGLTF3_REALLOC(ptr, sz) test_realloc((ptr), (sz))
|
||||
#define TINYGLTF3_FREE(ptr) test_free(ptr)
|
||||
#define TINYGLTF3_IMPLEMENTATION
|
||||
#include "tiny_gltf_v3.h"
|
||||
|
||||
static int streq(tg3_str s, const char *lit, uint32_t len) {
|
||||
uint32_t i;
|
||||
if (!s.data || s.len != len) return 0;
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (s.data[i] != lit[i]) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
static const uint8_t json[] =
|
||||
"{\"asset\":{\"version\":\"2.0\"},\"nodes\":[{\"name\":\"free\"}]}";
|
||||
tg3_model model;
|
||||
tg3_error_stack errors;
|
||||
tg3_parse_options opts;
|
||||
tg3_error_code err;
|
||||
|
||||
tg3_error_stack_init(&errors);
|
||||
tg3_parse_options_init(&opts);
|
||||
err = tg3_parse_auto(&model, &errors, json, (uint64_t)(sizeof(json) - 1),
|
||||
"", 0, &opts);
|
||||
if (err != TG3_OK) return 1;
|
||||
if (model.nodes_count != 1) return 3;
|
||||
if (!streq(model.nodes[0].name, "free", 4)) return 4;
|
||||
tg3_model_free(&model);
|
||||
tg3_error_stack_free(&errors);
|
||||
return 0;
|
||||
}
|
||||
165
tests/tester_v3_json_c.c
Normal file
165
tests/tester_v3_json_c.c
Normal file
@@ -0,0 +1,165 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TINYGLTF_JSON_C_IMPLEMENTATION
|
||||
#include "tinygltf_json_c.h"
|
||||
|
||||
static uint64_t dbl_bits(double v) {
|
||||
uint64_t bits;
|
||||
memcpy(&bits, &v, sizeof(bits));
|
||||
return bits;
|
||||
}
|
||||
|
||||
static double dbl_from_bits(uint64_t bits) {
|
||||
double v;
|
||||
memcpy(&v, &bits, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
static int check_stringify(const char *json, const char *expected) {
|
||||
tg3json_value v;
|
||||
const char *err = NULL;
|
||||
char *out;
|
||||
size_t out_len = 0;
|
||||
int ok = 1;
|
||||
if (!tg3json_parse(json, json + strlen(json), 128, &v, &err)) {
|
||||
fprintf(stderr, "parse failed for %s at %td\n", json, err ? err - json : -1);
|
||||
return 0;
|
||||
}
|
||||
out = tg3json_stringify(&v, &out_len);
|
||||
if (!out || strcmp(out, expected) != 0) {
|
||||
fprintf(stderr, "stringify(%s) = %s, expected %s\n",
|
||||
json, out ? out : "(null)", expected);
|
||||
ok = 0;
|
||||
}
|
||||
if (out) TINYGLTF_JSON_FREE(out);
|
||||
tg3json_value_free(&v);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int check_parse_rejects(const char *json) {
|
||||
tg3json_value v;
|
||||
const char *err = NULL;
|
||||
if (tg3json_parse(json, json + strlen(json), 128, &v, &err)) {
|
||||
fprintf(stderr, "parse unexpectedly accepted %s\n", json);
|
||||
tg3json_value_free(&v);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_roundtrip(const char *json) {
|
||||
tg3json_value a;
|
||||
tg3json_value b;
|
||||
const char *err = NULL;
|
||||
char *out;
|
||||
size_t out_len = 0;
|
||||
int ok = 1;
|
||||
if (!tg3json_parse(json, json + strlen(json), 128, &a, &err)) return 0;
|
||||
out = tg3json_stringify(&a, &out_len);
|
||||
if (!out || !tg3json_parse(out, out + out_len, 128, &b, &err)) {
|
||||
ok = 0;
|
||||
} else if (a.type != TG3JSON_REAL ||
|
||||
!((b.type == TG3JSON_REAL && dbl_bits(a.u.real) == dbl_bits(b.u.real)) ||
|
||||
(b.type == TG3JSON_INT && dbl_bits(a.u.real) == dbl_bits((double)b.u.integer)))) {
|
||||
fprintf(stderr, "roundtrip changed bits: %s -> %s\n", json, out);
|
||||
ok = 0;
|
||||
}
|
||||
if (out) TINYGLTF_JSON_FREE(out);
|
||||
tg3json_value_free(&a);
|
||||
tg3json_value_free(&b);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int check_parse_bits(const char *json, uint64_t expected_bits) {
|
||||
tg3json_value v;
|
||||
const char *err = NULL;
|
||||
if (!tg3json_parse(json, json + strlen(json), 128, &v, &err)) {
|
||||
fprintf(stderr, "parse failed for %s at %td\n", json, err ? err - json : -1);
|
||||
return 0;
|
||||
}
|
||||
if (v.type != TG3JSON_REAL || dbl_bits(v.u.real) != expected_bits) {
|
||||
fprintf(stderr, "parse bits mismatch: %s -> 0x%llx, expected 0x%llx\n",
|
||||
json, (unsigned long long)(v.type == TG3JSON_REAL ? dbl_bits(v.u.real) : 0),
|
||||
(unsigned long long)expected_bits);
|
||||
tg3json_value_free(&v);
|
||||
return 0;
|
||||
}
|
||||
tg3json_value_free(&v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_parse_float32(void) {
|
||||
static const char json[] = "0.10000000149011612";
|
||||
tg3json_parse_options opts;
|
||||
tg3json_value v;
|
||||
const char *err = NULL;
|
||||
double expected = (double)(float)0.10000000149011612;
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.parse_float32 = 1;
|
||||
if (!tg3json_parse_n_opts(json, strlen(json), &opts, &v, &err)) {
|
||||
fprintf(stderr, "parse_float32 parse failed\n");
|
||||
return 0;
|
||||
}
|
||||
if (v.type != TG3JSON_REAL || dbl_bits(v.u.real) != dbl_bits(expected)) {
|
||||
fprintf(stderr, "parse_float32 did not round through float\n");
|
||||
tg3json_value_free(&v);
|
||||
return 0;
|
||||
}
|
||||
tg3json_value_free(&v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_nonfinite_stringifies_to_null(void) {
|
||||
tg3json_value v;
|
||||
char *out;
|
||||
size_t len = 0;
|
||||
int ok;
|
||||
tg3json_value_init_real(&v, dbl_from_bits(0x7ff0000000000000ULL));
|
||||
out = tg3json_stringify(&v, &len);
|
||||
ok = out && strcmp(out, "null") == 0;
|
||||
if (!ok) fprintf(stderr, "inf stringify = %s\n", out ? out : "(null)");
|
||||
if (out) TINYGLTF_JSON_FREE(out);
|
||||
tg3json_value_free(&v);
|
||||
if (!ok) return 0;
|
||||
|
||||
tg3json_value_init_real(&v, dbl_from_bits(0x7ff8000000000001ULL));
|
||||
out = tg3json_stringify(&v, &len);
|
||||
ok = out && strcmp(out, "null") == 0;
|
||||
if (!ok) fprintf(stderr, "nan stringify = %s\n", out ? out : "(null)");
|
||||
if (out) TINYGLTF_JSON_FREE(out);
|
||||
tg3json_value_free(&v);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int ok = 1;
|
||||
ok = check_stringify("1.0", "1") && ok;
|
||||
ok = check_stringify("-1.0", "-1") && ok;
|
||||
ok = check_stringify("0.1", "0.1") && ok;
|
||||
ok = check_stringify("0.0001", "0.0001") && ok;
|
||||
ok = check_stringify("0.00001", "1e-5") && ok;
|
||||
ok = check_stringify("1000000000000000.0", "1000000000000000") && ok;
|
||||
ok = check_stringify("10000000000000000.0", "1e16") && ok;
|
||||
ok = check_roundtrip("1.2345678901234567") && ok;
|
||||
ok = check_roundtrip("2.2250738585072014e-308") && ok;
|
||||
ok = check_roundtrip("5e-324") && ok;
|
||||
ok = check_roundtrip("-5e-324") && ok;
|
||||
ok = check_roundtrip("9007199254740993.0") && ok;
|
||||
ok = check_parse_bits("1.23456789012345678901", 0x3ff3c0ca428c59fbULL) && ok;
|
||||
ok = check_parse_bits("1.234567890123456789012345678901234567890e-100",
|
||||
0x2b31482fe620c5d2ULL) && ok;
|
||||
ok = check_parse_bits("1.7976931348623157e308", 0x7fefffffffffffffULL) && ok;
|
||||
ok = check_parse_float32() && ok;
|
||||
ok = check_nonfinite_stringifies_to_null() && ok;
|
||||
ok = check_parse_rejects("+1") && ok;
|
||||
ok = check_parse_rejects("01") && ok;
|
||||
ok = check_parse_rejects("1.") && ok;
|
||||
ok = check_parse_rejects("1e") && ok;
|
||||
ok = check_parse_rejects("1e400") && ok;
|
||||
ok = check_parse_rejects("-1e400") && ok;
|
||||
ok = check_parse_rejects("1.7976931348623159e308") && ok;
|
||||
ok = check_parse_rejects("[1,]") && ok;
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
@@ -7059,7 +7059,11 @@ static void SerializeNumberProperty(const std::string &key, T number,
|
||||
detail::JsonAddMember(obj, key.c_str(), detail::json(number));
|
||||
}
|
||||
|
||||
#ifdef TINYGLTF_USE_RAPIDJSON
|
||||
#if defined(TINYGLTF_USE_RAPIDJSON) || defined(TINYGLTF_USE_CUSTOM_JSON)
|
||||
// size_t needs an explicit cast to uint64_t: on platforms where size_t is
|
||||
// neither int64_t nor uint64_t (e.g. macOS ARM64 where it is unsigned long,
|
||||
// or 32-bit targets where it is unsigned int) constructing detail::json
|
||||
// directly from a size_t is an ambiguous overload.
|
||||
template <>
|
||||
void SerializeNumberProperty(const std::string &key, size_t number,
|
||||
detail::json &obj) {
|
||||
|
||||
647
tiny_gltf_v3.c
647
tiny_gltf_v3.c
File diff suppressed because it is too large
Load Diff
@@ -116,8 +116,12 @@
|
||||
|
||||
/* Assert override */
|
||||
#ifndef TINYGLTF3_ASSERT
|
||||
#ifndef TINYGLTF3_NO_STDLIB
|
||||
#include <assert.h>
|
||||
#define TINYGLTF3_ASSERT(x) assert(x)
|
||||
#else
|
||||
#define TINYGLTF3_ASSERT(x) ((void)(x))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ======================================================================
|
||||
@@ -127,8 +131,34 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#ifndef TINYGLTF3_NO_STDLIB
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef TINYGLTF3_MALLOC
|
||||
#ifndef TINYGLTF3_NO_STDLIB
|
||||
#define TINYGLTF3_MALLOC(sz) malloc(sz)
|
||||
#else
|
||||
#define TINYGLTF3_MALLOC(sz) NULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TINYGLTF3_REALLOC
|
||||
#ifndef TINYGLTF3_NO_STDLIB
|
||||
#define TINYGLTF3_REALLOC(ptr, sz) realloc((ptr), (sz))
|
||||
#else
|
||||
#define TINYGLTF3_REALLOC(ptr, sz) NULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TINYGLTF3_FREE
|
||||
#ifndef TINYGLTF3_NO_STDLIB
|
||||
#define TINYGLTF3_FREE(ptr) free(ptr)
|
||||
#else
|
||||
#define TINYGLTF3_FREE(ptr) ((void)(ptr))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ======================================================================
|
||||
* Section 4: Constants and Enums
|
||||
@@ -418,6 +448,7 @@ typedef struct tg3_asset {
|
||||
/* --- Buffer --- */
|
||||
typedef struct tg3_buffer {
|
||||
tg3_str name;
|
||||
uint64_t byte_length; /* Declared buffer.byteLength */
|
||||
tg3_span_u8 data;
|
||||
tg3_str uri;
|
||||
tg3_extras_ext ext;
|
||||
@@ -941,6 +972,10 @@ typedef struct tg3_parse_options {
|
||||
int32_t images_as_is; /* 1 = don't decode images */
|
||||
int32_t preserve_image_channels; /* 1 = keep original channels */
|
||||
int32_t store_original_json; /* 1 = store raw JSON strings */
|
||||
int32_t skip_extras_values; /* 1 = skip materializing extras and
|
||||
* unknown extension value trees */
|
||||
int32_t borrow_input_buffers; /* 1 = GLB BIN buffer spans may point
|
||||
* into caller-owned input data */
|
||||
int32_t parse_float32; /* 1 = parse JSON floats as float32 for speed
|
||||
* (breaks strict double-precision conformance
|
||||
* but sufficient for glTF data which is
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user