Run v3 C tests with CMake and Meson

This commit is contained in:
Syoyo Fujita
2026-06-01 18:31:49 +09:00
parent 34a166cdac
commit 381daedaba
8 changed files with 392 additions and 62 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,62 +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_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_test(NAME tester_v3_c COMMAND tester_v3_c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_executable(tester_v3_c_v1port
tests/tester_v3_c_v1port.c
tiny_gltf_v3.c
)
target_include_directories(tester_v3_c_v1port PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/tests
)
set_target_properties(tester_v3_c_v1port PROPERTIES
C_STANDARD 11
C_STANDARD_REQUIRED ON
C_EXTENSIONS OFF
)
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_test(NAME tester_v3_c_v1port COMMAND tester_v3_c_v1port WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_executable(tester_v3_json_c tests/tester_v3_json_c.c)
target_include_directories(tester_v3_json_c PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
set_target_properties(tester_v3_json_c PROPERTIES
C_STANDARD 11
C_STANDARD_REQUIRED ON
C_EXTENSIONS OFF
)
add_test(NAME tester_v3_json_c COMMAND tester_v3_json_c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_tinygltf_v3_c_test(tester_v3_json_c tests/tester_v3_json_c.c)
add_executable(tester_v3_freestanding tests/tester_v3_freestanding.c)
target_include_directories(tester_v3_freestanding PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
set_target_properties(tester_v3_freestanding PROPERTIES
C_STANDARD 11
C_STANDARD_REQUIRED ON
C_EXTENSIONS OFF
)
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()
add_test(NAME tester_v3_freestanding COMMAND tester_v3_freestanding WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
endif (TINYGLTF_BUILD_TESTS)
#

52
meson.build Normal file
View 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
View File

@@ -0,0 +1 @@
option('tests', type: 'boolean', value: true, description: 'Build and run tinygltf tests')

View File

@@ -1372,6 +1372,255 @@ static int check_borrow_input_buffers(void) {
return ok;
}
static int parse_path_for_test(tg3_model *model, tg3_error_stack *errors,
const char *path, const tg3_parse_options *opts) {
FILE *fp;
uint8_t *buf;
long sz;
size_t got;
const char *slash;
uint32_t base_len;
tg3_error_code err;
memset(model, 0, sizeof(*model));
fp = fopen(path, "rb");
if (!fp) {
fprintf(stderr, "open failed: %s\n", path);
return 0;
}
if (fseek(fp, 0, SEEK_END) != 0 || (sz = ftell(fp)) < 0 ||
fseek(fp, 0, SEEK_SET) != 0) {
fprintf(stderr, "seek failed: %s\n", path);
fclose(fp);
return 0;
}
buf = (uint8_t *)malloc((size_t)sz);
if (!buf) {
fprintf(stderr, "alloc failed: %s\n", path);
fclose(fp);
return 0;
}
got = fread(buf, 1, (size_t)sz, fp);
fclose(fp);
if (got != (size_t)sz) {
fprintf(stderr, "short read: %s\n", path);
free(buf);
return 0;
}
slash = strrchr(path, '/');
base_len = slash ? (uint32_t)(slash - path) : 0;
err = tg3_parse_auto(model, errors, buf, (uint64_t)sz, path, base_len, opts);
free(buf);
if (err != TG3_OK) {
fprintf(stderr, "parse failed: %s err=%d\n", path, (int)err);
return 0;
}
return 1;
}
static int has_str(const tg3_str *items, uint32_t count, const char *needle) {
uint32_t i;
for (i = 0; i < count; ++i) {
if (tg3_str_equals_cstr(items[i], needle)) return 1;
}
return 0;
}
static int ext_has(const tg3_extras_ext *ext, const char *name) {
uint32_t i;
if (!ext || !ext->extensions) return 0;
for (i = 0; i < ext->extensions_count; ++i) {
if (tg3_str_equals_cstr(ext->extensions[i].name, name)) return 1;
}
return 0;
}
static int check_stdio_parse_regression_files(void) {
tg3_model model;
tg3_error_stack errors;
tg3_parse_options opts;
int ok = 1;
tg3_parse_options_init(&opts);
tg3_error_stack_init(&errors);
if (!parse_path_for_test(&model, &errors, "../models/Extensions-issue97/test.gltf", &opts) ||
model.extensions_used_count != 1 ||
!has_str(model.extensions_used, model.extensions_used_count,
"VENDOR_material_some_ext") ||
model.materials_count != 1 ||
!ext_has(&model.materials[0].ext, "VENDOR_material_some_ext")) {
fprintf(stderr, "issue-97 extension parse regression failed\n");
ok = 0;
}
tg3_model_free(&model);
tg3_error_stack_free(&errors);
if (!ok) return 0;
tg3_error_stack_init(&errors);
if (!parse_path_for_test(&model, &errors,
"../models/Extensions-overwrite-issue261/issue-261.gltf",
&opts) ||
!has_str(model.extensions_used, model.extensions_used_count,
"KHR_lights_punctual") ||
!ext_has(&model.ext, "NV_MDL") ||
!ext_has(&model.ext, "KHR_lights_punctual")) {
fprintf(stderr, "issue-261 extension overwrite regression failed\n");
ok = 0;
}
tg3_model_free(&model);
tg3_error_stack_free(&errors);
if (!ok) return 0;
tg3_error_stack_init(&errors);
if (!parse_path_for_test(&model, &errors,
"../models/regression/unassigned-skeleton.gltf",
&opts) ||
model.skins_count != 1 || model.skins[0].skeleton != -1) {
fprintf(stderr, "issue-321 unassigned skeleton regression failed\n");
ok = 0;
}
tg3_model_free(&model);
tg3_error_stack_free(&errors);
if (!ok) return 0;
tg3_error_stack_init(&errors);
if (!parse_path_for_test(&model, &errors,
"../models/regression/zero-sized-bin-chunk-issue-440.glb",
&opts)) {
fprintf(stderr, "issue-440 zero-sized BIN chunk regression failed\n");
ok = 0;
}
tg3_model_free(&model);
tg3_error_stack_free(&errors);
if (!ok) return 0;
tg3_error_stack_init(&errors);
if (!parse_path_for_test(&model, &errors, "issue-492.glb", &opts)) {
fprintf(stderr, "issue-492 inverse bind matrices regression failed\n");
ok = 0;
}
tg3_model_free(&model);
tg3_error_stack_free(&errors);
return ok;
}
static int check_stdio_parse_file_cube(void) {
tg3_model model;
tg3_error_stack errors;
tg3_parse_options opts;
tg3_error_code err;
int ok;
tg3_error_stack_init(&errors);
tg3_parse_options_init(&opts);
opts.images_as_is = 1;
err = tg3_parse_file(&model, &errors, "../models/Cube/Cube.gltf", 24, &opts);
ok = (err == TG3_OK && model.buffers_count == 1 &&
model.buffers[0].data.data && model.buffers[0].data.count > 0 &&
model.images_count == 2 && model.images[0].uri.data);
if (!ok) {
fprintf(stderr, "stdio parse_file Cube regression failed: err=%d\n", (int)err);
}
tg3_model_free(&model);
tg3_error_stack_free(&errors);
return ok;
}
static int write_read_stdio_roundtrip(const uint8_t *json, uint64_t json_size,
const char *path,
int (*check_model)(const tg3_model *model)) {
tg3_model model;
tg3_model roundtrip;
tg3_error_stack errors;
tg3_parse_options parse_opts;
tg3_write_options write_opts;
tg3_error_code err;
int ok = 0;
tg3_error_stack_init(&errors);
tg3_parse_options_init(&parse_opts);
tg3_write_options_init(&write_opts);
err = tg3_parse(&model, &errors, json, json_size, "", 0, &parse_opts);
if (err != TG3_OK) {
fprintf(stderr, "stdio write source parse failed: err=%d\n", (int)err);
goto done;
}
err = tg3_write_to_file(&model, &errors, path, (uint32_t)strlen(path), &write_opts);
if (err != TG3_OK) {
fprintf(stderr, "stdio write_to_file failed: %s err=%d\n", path, (int)err);
goto done_model;
}
err = tg3_parse_file(&roundtrip, &errors, path, (uint32_t)strlen(path), &parse_opts);
if (err != TG3_OK) {
fprintf(stderr, "stdio parse_file roundtrip failed: %s err=%d\n", path, (int)err);
goto done_model;
}
ok = check_model(&roundtrip);
tg3_model_free(&roundtrip);
done_model:
tg3_model_free(&model);
done:
remove(path);
tg3_error_stack_free(&errors);
return ok;
}
static int check_empty_node_scene_material_model(const tg3_model *model) {
return model->nodes_count == 1 &&
model->scenes_count == 1 &&
model->materials_count == 1 &&
model->scenes[0].nodes_count == 1 &&
model->scenes[0].nodes[0] == 0;
}
static int check_light_lod_model(const tg3_model *model) {
return model->lights_count == 1 &&
model->nodes_count == 3 &&
model->nodes[0].light == 0 &&
model->nodes[0].lods_count == 2 &&
model->nodes[0].lods[0] == 1 &&
model->nodes[0].lods[1] == 2 &&
model->scenes_count == 1 &&
model->scenes[0].nodes_count == 1 &&
model->scenes[0].nodes[0] == 0;
}
static int check_stdio_write_regression_cases(void) {
static const uint8_t empty_node_scene_material[] =
"{\"asset\":{\"version\":\"2.0\"},"
"\"nodes\":[{}],"
"\"scenes\":[{\"nodes\":[0]}],"
"\"materials\":[{}]}";
static const uint8_t light_lod[] =
"{\"asset\":{\"version\":\"2.0\"},"
"\"extensionsUsed\":[\"KHR_lights_punctual\",\"MSFT_lod\"],"
"\"extensions\":{\"KHR_lights_punctual\":{\"lights\":[{"
"\"type\":\"point\",\"intensity\":0.75,\"color\":[1.0,0.8,0.95]}]}},"
"\"nodes\":[{\"extensions\":{\"KHR_lights_punctual\":{\"light\":0},"
"\"MSFT_lod\":{\"ids\":[1,2]}}},{},{}],"
"\"scenes\":[{\"nodes\":[0]}]}";
if (!write_read_stdio_roundtrip(
empty_node_scene_material,
(uint64_t)(sizeof(empty_node_scene_material) - 1),
"tg3_v3_empty_node_scene_material.gltf",
check_empty_node_scene_material_model)) {
fprintf(stderr, "empty node/scene/material stdio roundtrip failed\n");
return 0;
}
if (!write_read_stdio_roundtrip(light_lod, (uint64_t)(sizeof(light_lod) - 1),
"tg3_v3_light_lod.gltf",
check_light_lod_model)) {
fprintf(stderr, "light/lod stdio roundtrip failed\n");
return 0;
}
return 1;
}
static int parse_file_arg(const char *path) {
FILE *fp = fopen(path, "rb");
uint8_t *buf;
@@ -1539,5 +1788,14 @@ int main(int argc, char **argv) {
if (!check_borrow_input_buffers()) {
return 1;
}
if (!check_stdio_parse_regression_files()) {
return 1;
}
if (!check_stdio_parse_file_cube()) {
return 1;
}
if (!check_stdio_write_regression_cases()) {
return 1;
}
return 0;
}

View File

@@ -641,6 +641,15 @@ static int tg3__u64_mul_overflow(uint64_t a, uint64_t b, uint64_t *out) {
return 0;
}
static int tg3__u64_fits_size(uint64_t v) {
#if SIZE_MAX < UINT64_MAX
return v <= (uint64_t)SIZE_MAX;
#else
(void)v;
return 1;
#endif
}
static int tg3__json_has(const tg3json_value *o, const char *key) {
return tg3json_object_get(o, key) ? 1 : 0;
}
@@ -1254,7 +1263,7 @@ static int tg3__parse_buffer(tg3__parse_ctx *ctx, const tg3json_value *o,
tg3__parse_extras_and_extensions(ctx, o, &buf->ext);
return 1;
}
if (byte_length > (uint64_t)((size_t)-1)) {
if (!tg3__u64_fits_size(byte_length)) {
tg3__error_push(ctx->errors, TG3_SEVERITY_ERROR, TG3_ERR_OUT_OF_MEMORY,
"buffer.byteLength exceeds addressable size", NULL, -1);
return 0;
@@ -1287,7 +1296,7 @@ static int tg3__parse_buffer(tg3__parse_ctx *ctx, const tg3json_value *o,
uint64_t file_size = 0;
if (tg3__load_external_file(ctx, &file_data, &file_size, buf->uri.data, buf->uri.len)) {
uint8_t *data = NULL;
if (file_size > (uint64_t)((size_t)-1)) {
if (!tg3__u64_fits_size(file_size)) {
tg3__error_push(ctx->errors, TG3_SEVERITY_ERROR, TG3_ERR_OUT_OF_MEMORY,
"external buffer exceeds addressable size", NULL, -1);
if (ctx->opts.fs.free_file) ctx->opts.fs.free_file(file_data, file_size, ctx->opts.fs.user_data);