переход на warcraftxl 1.1
This commit is contained in:
+17
-9
@@ -1,16 +1,24 @@
|
|||||||
[submodule "vendor/modules/wxl-modern-assets"]
|
|
||||||
path = vendor/modules/wxl-modern-assets
|
|
||||||
url = https://github.com/WarcraftXL/wxl-modern-assets.git
|
|
||||||
branch = main
|
|
||||||
[submodule "vendor/modules/wxl-modern-render"]
|
|
||||||
path = vendor/modules/wxl-modern-render
|
|
||||||
url = https://github.com/WarcraftXL/wxl-modern-render.git
|
|
||||||
branch = main
|
|
||||||
[submodule "vendor/modules/wxl-unit-outline"]
|
[submodule "vendor/modules/wxl-unit-outline"]
|
||||||
path = vendor/modules/wxl-unit-outline
|
path = vendor/modules/wxl-unit-outline
|
||||||
url = https://github.com/WarcraftXL/wxl-unit-outline.git
|
url = https://github.com/WarcraftXL/wxl-unit-outline.git
|
||||||
branch = main
|
branch = v1.1
|
||||||
[submodule "vendor/modules/wxl-modern-adt"]
|
[submodule "vendor/modules/wxl-modern-adt"]
|
||||||
path = vendor/modules/wxl-modern-adt
|
path = vendor/modules/wxl-modern-adt
|
||||||
url = https://github.com/WarcraftXL/wxl-modern-adt.git
|
url = https://github.com/WarcraftXL/wxl-modern-adt.git
|
||||||
branch = main
|
branch = main
|
||||||
|
[submodule "vendor/warcraftxl"]
|
||||||
|
path = vendor/warcraftxl
|
||||||
|
url = https://github.com/WarcraftXL/wxl-core.git
|
||||||
|
branch = v1.1
|
||||||
|
[submodule "vendor/modules/wxl-db2"]
|
||||||
|
path = vendor/modules/wxl-db2
|
||||||
|
url = https://github.com/WarcraftXL/wxl-db2.git
|
||||||
|
[submodule "vendor/modules/wxl-modern-m2"]
|
||||||
|
path = vendor/modules/wxl-modern-m2
|
||||||
|
url = https://github.com/WarcraftXL/wxl-modern-m2.git
|
||||||
|
[submodule "vendor/modules/wxl-modern-wmo"]
|
||||||
|
path = vendor/modules/wxl-modern-wmo
|
||||||
|
url = https://github.com/WarcraftXL/wxl-modern-wmo.git
|
||||||
|
[submodule "vendor/modules/wxl-grasswind"]
|
||||||
|
path = vendor/modules/wxl-grasswind
|
||||||
|
url = https://github.com/WarcraftXL/wxl-grasswind.git
|
||||||
|
|||||||
+63
-53
@@ -1,67 +1,77 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
project(MoonWellWarcraftXL LANGUAGES CXX)
|
project(MoonWellWarcraftXL LANGUAGES CXX)
|
||||||
|
|
||||||
# WarcraftXL remains an upstream submodule. MoonWell modules are attached to
|
# WarcraftXL is an untouched upstream v1.1 submodule. Every project-specific
|
||||||
# its aggregate DLL target here, so updating the framework does not mix our
|
# feature below is built as a separately loaded Extensions/<name>/<name>.dll.
|
||||||
# client-specific offsets and policy into the upstream checkout.
|
|
||||||
add_subdirectory(vendor/warcraftxl)
|
add_subdirectory(vendor/warcraftxl)
|
||||||
|
|
||||||
|
set(WXL_CORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/warcraftxl")
|
||||||
set(WXL_EXTERNAL_MODULES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/modules")
|
set(WXL_EXTERNAL_MODULES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/modules")
|
||||||
|
set(WXL_LOCAL_MODULES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/modules")
|
||||||
|
|
||||||
function(wxl_collect_sources output)
|
function(wxl_add_external_extension extension_name extension_dir)
|
||||||
file(GLOB_RECURSE collected CONFIGURE_DEPENDS ${ARGN})
|
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
set(${output} "${collected}" PARENT_SCOPE)
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GLOB_RECURSE extension_sources CONFIGURE_DEPENDS "${extension_dir}/src/*.cpp")
|
||||||
|
if(NOT extension_sources)
|
||||||
|
message(FATAL_ERROR "WarcraftXL extension '${extension_name}' has no sources in ${extension_dir}/src")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(extension_shared_sources "")
|
||||||
|
if(extension_name STREQUAL "wxl-modern-m2")
|
||||||
|
file(GLOB_RECURSE extension_shared_sources CONFIGURE_DEPENDS
|
||||||
|
"${WXL_CORE_DIR}/src/engine/assets/shared/models/m2/*.cpp")
|
||||||
|
elseif(extension_name STREQUAL "wxl-modern-blp")
|
||||||
|
file(GLOB_RECURSE extension_shared_sources CONFIGURE_DEPENDS
|
||||||
|
"${WXL_CORE_DIR}/src/engine/assets/shared/textures/blp/*.cpp")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GLOB wxl_sdk_sources CONFIGURE_DEPENDS "${WXL_CORE_DIR}/src/game/*.cpp")
|
||||||
|
add_library(${extension_name} SHARED
|
||||||
|
${extension_sources}
|
||||||
|
${extension_shared_sources}
|
||||||
|
${wxl_sdk_sources})
|
||||||
|
set_target_properties(${extension_name} PROPERTIES
|
||||||
|
OUTPUT_NAME "${extension_name}"
|
||||||
|
PREFIX "")
|
||||||
|
target_include_directories(${extension_name} PRIVATE
|
||||||
|
"${extension_dir}/src"
|
||||||
|
"${WXL_CORE_DIR}/include"
|
||||||
|
"${WXL_CORE_DIR}/src")
|
||||||
|
target_compile_features(${extension_name} PRIVATE cxx_std_20)
|
||||||
|
target_compile_definitions(${extension_name} PRIVATE
|
||||||
|
WIN32_LEAN_AND_MEAN NOMINMAX _CRT_SECURE_NO_WARNINGS WXL_EXTENSION)
|
||||||
|
|
||||||
|
if(CLIENT_PATH)
|
||||||
|
add_custom_command(TARGET ${extension_name} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||||
|
"${CLIENT_PATH}/Extensions/${extension_name}"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:${extension_name}>"
|
||||||
|
"${CLIENT_PATH}/Extensions/${extension_name}/${extension_name}.dll"
|
||||||
|
COMMENT "Deploy ${extension_name}.dll -> Extensions/${extension_name}")
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
if(TARGET WarcraftXL)
|
# Official WarcraftXL 1.1 extensions.
|
||||||
wxl_collect_sources(WXL_MODERN_ASSETS_RUNTIME
|
wxl_add_external_extension(wxl-db2 "${WXL_EXTERNAL_MODULES_DIR}/wxl-db2")
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-assets/src/*.cpp"
|
wxl_add_external_extension(wxl-modern-adt "${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-adt")
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-assets/shared/*.cpp")
|
wxl_add_external_extension(wxl-modern-blp "${WXL_LOCAL_MODULES_DIR}/wxl-modern-blp")
|
||||||
if(WXL_MODERN_ASSETS_EXCLUDE_REGEX)
|
wxl_add_external_extension(wxl-modern-m2 "${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-m2")
|
||||||
list(FILTER WXL_MODERN_ASSETS_RUNTIME EXCLUDE REGEX
|
wxl_add_external_extension(wxl-modern-wmo "${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-wmo")
|
||||||
"${WXL_MODERN_ASSETS_EXCLUDE_REGEX}")
|
wxl_add_external_extension(wxl-grasswind "${WXL_EXTERNAL_MODULES_DIR}/wxl-grasswind")
|
||||||
endif()
|
wxl_add_external_extension(wxl-unit-outline "${WXL_EXTERNAL_MODULES_DIR}/wxl-unit-outline")
|
||||||
wxl_collect_sources(WXL_MODERN_RENDER_RUNTIME
|
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-render/src/*.cpp")
|
|
||||||
wxl_collect_sources(WXL_UNIT_OUTLINE_RUNTIME
|
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-unit-outline/src/*.cpp")
|
|
||||||
wxl_collect_sources(WXL_MODERN_ADT_RUNTIME
|
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-adt/src/*.cpp"
|
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-adt/shared/*.cpp")
|
|
||||||
|
|
||||||
target_sources(WarcraftXL PRIVATE
|
# MoonWell-owned extensions. wxl-fdid-moonwell sorts after wxl-db2 and before
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/modules/moonwell/src/MoonWell.cpp"
|
# the modern asset extensions, so it can layer custom CSV mappings over wxl.fdid.
|
||||||
${WXL_MODERN_ASSETS_RUNTIME}
|
wxl_add_external_extension(MoonWell "${WXL_LOCAL_MODULES_DIR}/moonwell")
|
||||||
${WXL_MODERN_RENDER_RUNTIME}
|
wxl_add_external_extension(wxl-fdid-moonwell "${WXL_LOCAL_MODULES_DIR}/moonwell-fdid")
|
||||||
${WXL_UNIT_OUTLINE_RUNTIME}
|
wxl_add_external_extension(wxl-moonwell-storage-fallback
|
||||||
${WXL_MODERN_ADT_RUNTIME})
|
"${WXL_LOCAL_MODULES_DIR}/moonwell-storage-fallback")
|
||||||
|
|
||||||
# wxl-modern-render needs its module-root includes and D3D12 import library.
|
# Recovery loader retained for existing -NativeRenderer workflows. WarcraftXL
|
||||||
include("${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-render/module.cmake")
|
# 1.1 already ships a native D3D9 forwarding proxy as its standard renderer.
|
||||||
endif()
|
|
||||||
|
|
||||||
if(TARGET WarcraftXLHost)
|
|
||||||
wxl_collect_sources(WXL_MOONWELL_HOST
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/modules/moonwell/host/*.cpp")
|
|
||||||
wxl_collect_sources(WXL_MODERN_ASSETS_HOST
|
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-assets/host/*.cpp"
|
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-assets/shared/*.cpp")
|
|
||||||
if(WXL_MODERN_ASSETS_EXCLUDE_REGEX)
|
|
||||||
list(FILTER WXL_MODERN_ASSETS_HOST EXCLUDE REGEX
|
|
||||||
"${WXL_MODERN_ASSETS_EXCLUDE_REGEX}")
|
|
||||||
endif()
|
|
||||||
wxl_collect_sources(WXL_MODERN_ADT_HOST
|
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-adt/host/*.cpp"
|
|
||||||
"${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-adt/shared/*.cpp")
|
|
||||||
|
|
||||||
target_sources(WarcraftXLHost PRIVATE
|
|
||||||
${WXL_MOONWELL_HOST}
|
|
||||||
${WXL_MODERN_ASSETS_HOST}
|
|
||||||
${WXL_MODERN_ADT_HOST})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Minimal native-D3D9 proxy retained as a recovery renderer. The regular
|
|
||||||
# package uses WarcraftXL's D3D9On12 proxy required by wxl-modern-render.
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
add_library(MoonWellLoader SHARED
|
add_library(MoonWellLoader SHARED
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/loader/d3d9.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/loader/d3d9.cpp"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Исходники клиентских изменений MoonWell для World of Warcraft 3.3.5a (build 12340).
|
Исходники клиентских изменений MoonWell для World of Warcraft 3.3.5a (build 12340).
|
||||||
|
|
||||||
Клиент переведён на [WarcraftXL](https://github.com/WarcraftXL): `Wow.exe` больше не содержит
|
Клиент переведён на [WarcraftXL](https://github.com/WarcraftXL/wxl-core) **1.1.220**: `Wow.exe` больше не содержит
|
||||||
MoonWell-патчей. Неподписанный оригинальный executable загружается как обычно, локальный
|
MoonWell-патчей. Неподписанный оригинальный executable загружается как обычно, локальный
|
||||||
`d3d9.dll` proxy подхватывает `WarcraftXL.dll`, а модуль MoonWell применяет проверенные изменения
|
`d3d9.dll` proxy подхватывает `WarcraftXL.dll`, а модуль MoonWell применяет проверенные изменения
|
||||||
только к памяти запущенного процесса.
|
только к памяти запущенного процесса.
|
||||||
@@ -14,25 +14,25 @@ MoonWell-патчей. Неподписанный оригинальный execu
|
|||||||
- одиннадцатое значение `GetCharacterInfo` — `charFlags`, включая флаг предателя `0x40000000`;
|
- одиннадцатое значение `GetCharacterInfo` — `charFlags`, включая флаг предателя `0x40000000`;
|
||||||
- загрузка WarcraftXL без import-table patch и без отдельного injector.
|
- загрузка WarcraftXL без import-table patch и без отдельного injector.
|
||||||
|
|
||||||
Large Address Aware намеренно не включён: Windows читает этот PE-флаг до загрузки DLL, поэтому
|
При установке сборщик включает Large Address Aware в копии `Wow.exe`; исходный
|
||||||
сохранить его и одновременно оставить файл байт-в-байт оригинальным невозможно. Это означает
|
`Wow_Original.exe` остаётся неизменным и используется как проверенный шаблон.
|
||||||
стандартный 2-ГБ лимит адресного пространства для 32-битного клиента.
|
|
||||||
|
|
||||||
## Структура
|
## Структура
|
||||||
|
|
||||||
```text
|
```text
|
||||||
modules/moonwell/ MoonWell runtime-модуль WarcraftXL
|
modules/ отдельные MoonWell extensions для WarcraftXL 1.1
|
||||||
vendor/warcraftxl/ закреплённый upstream git submodule
|
vendor/warcraftxl/ закреплённый upstream git submodule
|
||||||
vendor/modules/ закреплённые модули WarcraftXL
|
vendor/modules/ закреплённые модули WarcraftXL
|
||||||
src/Data/ исходники MPQ-патчей
|
src/Data/ исходники MPQ-патчей
|
||||||
tool/ сборщик MPQ
|
tool/ сборщик MPQ
|
||||||
build-warcraftxl.ps1 сборка Win32 runtime/proxy и x64 asset host
|
build-warcraftxl.ps1 сборка Win32 runtime, proxy и extensions
|
||||||
run.ps1 полная сборка, установка и запуск клиента
|
run.ps1 полная сборка, установка и запуск клиента
|
||||||
Wow_Original.exe локальный оригинал build 12340 (не хранится в Git)
|
Wow_Original.exe локальный оригинал build 12340 (не хранится в Git)
|
||||||
```
|
```
|
||||||
|
|
||||||
Подключены модули `wxl-modern-assets`, `wxl-modern-render`, `wxl-unit-outline` и
|
Подключены совместимые с 1.1 extensions: `wxl-db2`, `wxl-modern-adt`, `wxl-modern-m2`,
|
||||||
`wxl-modern-adt`. Их точные ревизии вместе с ревизией ядра закреплены git submodule.
|
`wxl-modern-wmo`, `wxl-grasswind` и `wxl-unit-outline`. BLP-адаптер и MoonWell-изменения
|
||||||
|
собираются как отдельные DLL; исходники upstream core не изменяются.
|
||||||
Для обновления всех зависимостей WarcraftXL:
|
Для обновления всех зависимостей WarcraftXL:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -44,7 +44,7 @@ git submodule update --remote vendor/warcraftxl vendor/modules/*
|
|||||||
|
|
||||||
## Требования
|
## Требования
|
||||||
|
|
||||||
- Visual Studio 2022 с C++ toolchain для Win32 и x64;
|
- Visual Studio 2022 с C++ toolchain для Win32;
|
||||||
- CMake 3.20+;
|
- CMake 3.20+;
|
||||||
- Rust/Cargo для существующего MPQ-сборщика;
|
- Rust/Cargo для существующего MPQ-сборщика;
|
||||||
- локальный оригинальный `Wow_Original.exe` с SHA-256
|
- локальный оригинальный `Wow_Original.exe` с SHA-256
|
||||||
@@ -64,7 +64,7 @@ git submodule update --init --recursive
|
|||||||
.\deploy.ps1
|
.\deploy.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
Скрипт инициализирует зависимости, собирает MPQ-патчи, Win32 runtime, D3D9 proxy и x64 Host,
|
Скрипт инициализирует зависимости, собирает MPQ-патчи, Win32 runtime, native D3D9 proxy и extensions,
|
||||||
обновляет `dist`, устанавливает комплект в клиент и формирует `manifest.json`. Путь берётся из
|
обновляет `dist`, устанавливает комплект в клиент и формирует `manifest.json`. Путь берётся из
|
||||||
`WOW_HOME`/`.env`, а при их отсутствии используется `C:\Program Files (x86)\World of Warcraft`.
|
`WOW_HOME`/`.env`, а при их отсутствии используется `C:\Program Files (x86)\World of Warcraft`.
|
||||||
|
|
||||||
@@ -77,8 +77,6 @@ git submodule update --init --recursive
|
|||||||
# Быстро обновить только WarcraftXL без пересборки MPQ
|
# Быстро обновить только WarcraftXL без пересборки MPQ
|
||||||
.\deploy.ps1 -SkipDataBuild
|
.\deploy.ps1 -SkipDataBuild
|
||||||
|
|
||||||
# Аварийный native D3D9 вместо D3D9On12
|
|
||||||
.\deploy.ps1 -NativeRenderer
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Без установки в клиент:
|
Без установки в клиент:
|
||||||
@@ -99,18 +97,8 @@ git submodule update --init --recursive
|
|||||||
1. проверяет хеш `Wow_Original.exe`;
|
1. проверяет хеш `Wow_Original.exe`;
|
||||||
2. сохраняет прежний модифицированный клиент как `Wow.moonwell-patched.backup.exe`;
|
2. сохраняет прежний модифицированный клиент как `Wow.moonwell-patched.backup.exe`;
|
||||||
3. восстанавливает оригинальный `Wow.exe`;
|
3. восстанавливает оригинальный `Wow.exe`;
|
||||||
4. устанавливает `WarcraftXL.dll`, D3D9On12 proxy и `Utils\WarcraftXLHost.exe`;
|
4. устанавливает `WarcraftXL.dll`, native D3D9 proxy и DLL в `Extensions\`;
|
||||||
5. монтирует шейдеры modern ADT как loose patch `Data\Patch-WXL.MPQ`;
|
5. при `-PackagePath` кладёт полный runtime-комплект в `dist` для launcher/S3.
|
||||||
6. при `-PackagePath` кладёт полный runtime-комплект в `dist` для launcher/S3.
|
|
||||||
|
|
||||||
Основной proxy использует D3D9On12, необходимый `wxl-modern-render`. Эффекты постобработки в самом
|
|
||||||
модуле по умолчанию выключены. Для диагностики или несовместимой видеосистемы можно собрать и
|
|
||||||
установить native-переходник без modern-render:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
.\build-warcraftxl.ps1 -Configuration Release -NativeRenderer `
|
|
||||||
-ClientPath 'C:\Program Files (x86)\World of Warcraft' -Deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
Резервная DLL всегда также сохраняется как `Utils\d3d9-native.dll`.
|
Резервная DLL всегда также сохраняется как `Utils\d3d9-native.dll`.
|
||||||
|
|
||||||
@@ -121,8 +109,7 @@ $env:WOW_HOME = 'C:\Program Files (x86)\World of Warcraft'
|
|||||||
.\run.ps1
|
.\run.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
Диагностика запуска находится в `Logs\wxl-core.log`, `Logs\d3d9proxy.log` и
|
Диагностика запуска находится в `Logs\wxl-core.log` и `Logs\d3d9proxy.log` внутри клиента.
|
||||||
`Utils\WarcraftXLHost.log` внутри клиента.
|
|
||||||
|
|
||||||
## MPQ-пакеты
|
## MPQ-пакеты
|
||||||
|
|
||||||
@@ -138,6 +125,6 @@ WarcraftXL не требуется и в объектное хранилище
|
|||||||
|
|
||||||
## Лицензирование
|
## Лицензирование
|
||||||
|
|
||||||
WarcraftXL распространяется по GPL-3.0 и подключён как отдельный upstream submodule. MoonWell-модуль,
|
WarcraftXL распространяется по GPL-3.0 и подключён как отдельный неизменённый upstream submodule.
|
||||||
скомпонованный в `WarcraftXL.dll`, должен распространяться с соблюдением GPL-3.0 и доступным
|
MoonWell extensions распространяются с доступным соответствующим исходным кодом. Репозиторий не
|
||||||
соответствующим исходным кодом. Репозиторий не должен публиковать Blizzard assets или `Wow.exe`.
|
должен публиковать Blizzard assets или `Wow.exe`.
|
||||||
|
|||||||
+35
-29
@@ -88,7 +88,6 @@ if (-not (Test-Path -LiteralPath $cmake)) {
|
|||||||
if ($LASTEXITCODE -ne 0) { throw 'Failed to initialize WarcraftXL submodules.' }
|
if ($LASTEXITCODE -ne 0) { throw 'Failed to initialize WarcraftXL submodules.' }
|
||||||
|
|
||||||
$win32BuildDir = Join-Path $repoRoot 'build\warcraftxl-win32'
|
$win32BuildDir = Join-Path $repoRoot 'build\warcraftxl-win32'
|
||||||
$hostBuildDir = Join-Path $repoRoot 'build\warcraftxl-host-x64'
|
|
||||||
$stockExe = Join-Path $repoRoot 'Wow_Original.exe'
|
$stockExe = Join-Path $repoRoot 'Wow_Original.exe'
|
||||||
|
|
||||||
if ($Deploy -or -not [string]::IsNullOrWhiteSpace($PackagePath)) {
|
if ($Deploy -or -not [string]::IsNullOrWhiteSpace($PackagePath)) {
|
||||||
@@ -104,22 +103,29 @@ if ($Deploy -or -not [string]::IsNullOrWhiteSpace($PackagePath)) {
|
|||||||
|
|
||||||
& $cmake -S $repoRoot -B $win32BuildDir -A Win32 '-DCLIENT_PATH='
|
& $cmake -S $repoRoot -B $win32BuildDir -A Win32 '-DCLIENT_PATH='
|
||||||
if ($LASTEXITCODE -ne 0) { throw 'WarcraftXL Win32 configure failed.' }
|
if ($LASTEXITCODE -ne 0) { throw 'WarcraftXL Win32 configure failed.' }
|
||||||
& $cmake --build $win32BuildDir --config $Configuration --target WarcraftXL d3d9 MoonWellLoader
|
& $cmake --build $win32BuildDir --config $Configuration --parallel 4
|
||||||
if ($LASTEXITCODE -ne 0) { throw 'WarcraftXL Win32 build failed.' }
|
if ($LASTEXITCODE -ne 0) { throw 'WarcraftXL Win32 build failed.' }
|
||||||
|
|
||||||
& $cmake -S $repoRoot -B $hostBuildDir -A x64 '-DWXL_BUILD_HOST=ON' '-DCLIENT_PATH='
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw 'WarcraftXL Host configure failed.' }
|
|
||||||
& $cmake --build $hostBuildDir --config $Configuration --target WarcraftXLHost
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw 'WarcraftXL Host build failed.' }
|
|
||||||
|
|
||||||
$win32ArtifactDir = Join-Path $win32BuildDir "vendor\warcraftxl\$Configuration"
|
$win32ArtifactDir = Join-Path $win32BuildDir "vendor\warcraftxl\$Configuration"
|
||||||
$hostArtifactDir = Join-Path $hostBuildDir "vendor\warcraftxl\$Configuration"
|
|
||||||
$warcraftXL = Join-Path $win32ArtifactDir 'WarcraftXL.dll'
|
$warcraftXL = Join-Path $win32ArtifactDir 'WarcraftXL.dll'
|
||||||
$modernProxy = Join-Path $win32ArtifactDir 'd3d9.dll'
|
$selectedProxy = Join-Path $win32ArtifactDir 'd3d9.dll'
|
||||||
$nativeProxy = Join-Path $win32BuildDir "artifacts\$Configuration\d3d9-native.dll"
|
$recoveryProxy = Join-Path $win32BuildDir "artifacts\$Configuration\d3d9-native.dll"
|
||||||
$hostExe = Join-Path $hostArtifactDir 'WarcraftXLHost.exe'
|
$extensionNames = @(
|
||||||
$selectedProxy = if ($NativeRenderer) { $nativeProxy } else { $modernProxy }
|
'MoonWell',
|
||||||
$adtResources = Join-Path $repoRoot 'vendor\modules\wxl-modern-adt\_resources'
|
'wxl-db2',
|
||||||
|
'wxl-fdid-moonwell',
|
||||||
|
'wxl-grasswind',
|
||||||
|
'wxl-modern-adt',
|
||||||
|
'wxl-modern-blp',
|
||||||
|
'wxl-modern-m2',
|
||||||
|
'wxl-modern-wmo',
|
||||||
|
'wxl-moonwell-storage-fallback',
|
||||||
|
'wxl-unit-outline'
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($NativeRenderer) {
|
||||||
|
Write-Warning '-NativeRenderer is no longer needed: WarcraftXL 1.1 uses native D3D9 by default.'
|
||||||
|
}
|
||||||
|
|
||||||
function Install-WarcraftXLArtifacts {
|
function Install-WarcraftXLArtifacts {
|
||||||
param(
|
param(
|
||||||
@@ -128,14 +134,18 @@ function Install-WarcraftXLArtifacts {
|
|||||||
)
|
)
|
||||||
|
|
||||||
$utils = Join-Path $Destination 'Utils'
|
$utils = Join-Path $Destination 'Utils'
|
||||||
$loosePatch = Join-Path $Destination 'Data\Patch-WXL.MPQ'
|
|
||||||
|
|
||||||
New-Item `
|
New-Item `
|
||||||
-ItemType Directory `
|
-ItemType Directory `
|
||||||
-Path $Destination, $utils, $loosePatch `
|
-Path $Destination, $utils `
|
||||||
-Force |
|
-Force |
|
||||||
Out-Null
|
Out-Null
|
||||||
|
|
||||||
|
$legacyHost = Join-Path $utils 'WarcraftXLHost.exe'
|
||||||
|
if (Test-Path -LiteralPath $legacyHost -PathType Leaf) {
|
||||||
|
Remove-Item -LiteralPath $legacyHost -Force
|
||||||
|
Write-Host "Removed obsolete WarcraftXL 1.0 host: $legacyHost"
|
||||||
|
}
|
||||||
|
|
||||||
$destinationExe = Join-Path $Destination 'Wow.exe'
|
$destinationExe = Join-Path $Destination 'Wow.exe'
|
||||||
|
|
||||||
Copy-Item `
|
Copy-Item `
|
||||||
@@ -156,20 +166,17 @@ function Install-WarcraftXLArtifacts {
|
|||||||
-Force
|
-Force
|
||||||
|
|
||||||
Copy-Item `
|
Copy-Item `
|
||||||
-LiteralPath $nativeProxy `
|
-LiteralPath $recoveryProxy `
|
||||||
-Destination (Join-Path $utils 'd3d9-native.dll') `
|
-Destination (Join-Path $utils 'd3d9-native.dll') `
|
||||||
-Force
|
-Force
|
||||||
|
|
||||||
Copy-Item `
|
foreach ($extensionName in $extensionNames) {
|
||||||
-LiteralPath $hostExe `
|
$extensionSource = Join-Path $win32BuildDir "$Configuration\$extensionName.dll"
|
||||||
-Destination (Join-Path $utils 'WarcraftXLHost.exe') `
|
$extensionDestination = Join-Path $Destination "Extensions\$extensionName"
|
||||||
-Force
|
New-Item -ItemType Directory -Path $extensionDestination -Force | Out-Null
|
||||||
|
|
||||||
Get-ChildItem -LiteralPath $adtResources | ForEach-Object {
|
|
||||||
Copy-Item `
|
Copy-Item `
|
||||||
-LiteralPath $_.FullName `
|
-LiteralPath $extensionSource `
|
||||||
-Destination $loosePatch `
|
-Destination (Join-Path $extensionDestination "$extensionName.dll") `
|
||||||
-Recurse `
|
|
||||||
-Force
|
-Force
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,7 +203,7 @@ if ($Deploy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Install-WarcraftXLArtifacts -Destination $ClientPath
|
Install-WarcraftXLArtifacts -Destination $ClientPath
|
||||||
Write-Host "Installed WarcraftXL runtime, host and modules in $ClientPath"
|
Write-Host "Installed WarcraftXL 1.1 runtime and extensions in $ClientPath"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not [string]::IsNullOrWhiteSpace($PackagePath)) {
|
if (-not [string]::IsNullOrWhiteSpace($PackagePath)) {
|
||||||
@@ -205,5 +212,4 @@ if (-not [string]::IsNullOrWhiteSpace($PackagePath)) {
|
|||||||
Write-Host "Packaged stock Wow.exe and WarcraftXL artifacts in $PackagePath"
|
Write-Host "Packaged stock Wow.exe and WarcraftXL artifacts in $PackagePath"
|
||||||
}
|
}
|
||||||
|
|
||||||
$renderer = if ($NativeRenderer) { 'native D3D9 recovery proxy' } else { 'WarcraftXL D3D9On12 proxy' }
|
Write-Host "WarcraftXL 1.1 build complete (native D3D9 proxy): $win32ArtifactDir"
|
||||||
Write-Host "WarcraftXL build complete ($renderer): $win32ArtifactDir"
|
|
||||||
|
|||||||
+2
-5
@@ -58,9 +58,6 @@ if ($runningClients.Count) {
|
|||||||
Write-Host 'Stopping the running WoW client...'
|
Write-Host 'Stopping the running WoW client...'
|
||||||
$runningClients | Stop-Process -Force
|
$runningClients | Stop-Process -Force
|
||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
Get-Process WarcraftXLHost -ErrorAction SilentlyContinue | Where-Object {
|
|
||||||
$_.Path -and $_.Path.StartsWith($ClientPath, [System.StringComparison]::OrdinalIgnoreCase)
|
|
||||||
} | Stop-Process -Force
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$env:WOW_HOME = $ClientPath
|
$env:WOW_HOME = $ClientPath
|
||||||
@@ -120,12 +117,12 @@ if (-not $SkipManifest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$wowHash = (Get-FileHash -LiteralPath (Join-Path $ClientPath 'Wow.exe') -Algorithm SHA256).Hash
|
$wowHash = (Get-FileHash -LiteralPath (Join-Path $ClientPath 'Wow.exe') -Algorithm SHA256).Hash
|
||||||
$renderer = if ($NativeRenderer) { 'native D3D9 recovery proxy' } else { 'WarcraftXL D3D9On12' }
|
$renderer = 'WarcraftXL 1.1 native D3D9 proxy'
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Host 'Deployment complete.'
|
Write-Host 'Deployment complete.'
|
||||||
Write-Host " Renderer: $renderer"
|
Write-Host " Renderer: $renderer"
|
||||||
Write-Host " Wow.exe SHA-256: $wowHash"
|
Write-Host " Wow.exe SHA-256: $wowHash"
|
||||||
Write-Host " Host: $(Join-Path $ClientPath 'Utils\WarcraftXLHost.exe')"
|
Write-Host " Extensions: $(Join-Path $ClientPath 'Extensions')"
|
||||||
|
|
||||||
if ($Launch) {
|
if ($Launch) {
|
||||||
Write-Host 'Launching Wow.exe...'
|
Write-Host 'Launching Wow.exe...'
|
||||||
|
|||||||
+2
-3
@@ -50,9 +50,8 @@ extern "C" HRESULT WINAPI Direct3DCreate9Ex(UINT sdkVersion, IDirect3D9Ex** outp
|
|||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compatibility exports referenced by the current WarcraftXL core. MoonWell
|
// Legacy compatibility exports retained for the recovery proxy. WarcraftXL 1.1
|
||||||
// does not enable its D3D9On12 backend, so these intentionally report no D3D12
|
// uses native D3D9 and ignores the former D3D9On12 bridge.
|
||||||
// device and a neutral supersampling factor.
|
|
||||||
extern "C" void* WxlD3D12Device() { return nullptr; }
|
extern "C" void* WxlD3D12Device() { return nullptr; }
|
||||||
extern "C" void* WxlD3D12Queue() { return nullptr; }
|
extern "C" void* WxlD3D12Queue() { return nullptr; }
|
||||||
extern "C" void WxlD3D12DrainDebug() {}
|
extern "C" void WxlD3D12DrainDebug() {}
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// FileDataID overlay for selected retail assets shipped in MoonWell patches.
|
||||||
|
|
||||||
|
#include "game/Io.hpp"
|
||||||
|
#include "wxl/FdidApi.h"
|
||||||
|
#include "wxl/PluginApi.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <charconv>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <system_error>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace moonwell::fdid
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr std::string_view kFileDataMap = "WXLFileData.csv";
|
||||||
|
|
||||||
|
std::once_flag g_loadOnce;
|
||||||
|
std::unordered_map<uint32_t, std::string> g_paths;
|
||||||
|
const WXL_Api* g_api = nullptr;
|
||||||
|
const char*(__cdecl* g_resolveTexture)(uint32_t) = nullptr;
|
||||||
|
const char*(__cdecl* g_resolveModel)(uint32_t) = nullptr;
|
||||||
|
|
||||||
|
bool ReadAll(const char* path, std::vector<uint8_t>& out)
|
||||||
|
{
|
||||||
|
void* handle = nullptr;
|
||||||
|
if (!wxl::game::io::FileOpen(path, wxl::game::io::kOpenWholeFile, &handle) || !handle)
|
||||||
|
return false;
|
||||||
|
uint32_t high = 0;
|
||||||
|
const uint32_t size = wxl::game::io::FileSize(handle, &high);
|
||||||
|
if (high != 0)
|
||||||
|
{
|
||||||
|
wxl::game::io::FileClose(handle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.resize(size);
|
||||||
|
uint32_t read = 0;
|
||||||
|
const bool ok = (size == 0 || wxl::game::io::FileRead(handle, out.data(), size, &read))
|
||||||
|
&& read == size;
|
||||||
|
wxl::game::io::FileClose(handle);
|
||||||
|
if (!ok) out.clear();
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view Trim(std::string_view value)
|
||||||
|
{
|
||||||
|
while (!value.empty() && (value.front() == ' ' || value.front() == '\t' ||
|
||||||
|
value.front() == '\r' || value.front() == '\n'))
|
||||||
|
value.remove_prefix(1);
|
||||||
|
while (!value.empty() && (value.back() == ' ' || value.back() == '\t' ||
|
||||||
|
value.back() == '\r' || value.back() == '\n'))
|
||||||
|
value.remove_suffix(1);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load()
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> bytes;
|
||||||
|
if (!ReadAll(kFileDataMap.data(), bytes))
|
||||||
|
{
|
||||||
|
if (g_api && g_api->Log)
|
||||||
|
g_api->Log(WXL_LOG_WARN, "MoonWellFdid", "FileDataID map '%s' was not found",
|
||||||
|
kFileDataMap.data());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string_view text(reinterpret_cast<const char*>(bytes.data()), bytes.size());
|
||||||
|
size_t lineStart = 0;
|
||||||
|
while (lineStart < text.size())
|
||||||
|
{
|
||||||
|
size_t lineEnd = text.find('\n', lineStart);
|
||||||
|
if (lineEnd == std::string_view::npos) lineEnd = text.size();
|
||||||
|
std::string_view line = Trim(text.substr(lineStart, lineEnd - lineStart));
|
||||||
|
lineStart = lineEnd + 1;
|
||||||
|
|
||||||
|
if (line.empty() || line.front() == '#') continue;
|
||||||
|
const size_t comma = line.find(',');
|
||||||
|
if (comma == std::string_view::npos) continue;
|
||||||
|
|
||||||
|
const std::string_view idText = Trim(line.substr(0, comma));
|
||||||
|
std::string_view pathText = Trim(line.substr(comma + 1));
|
||||||
|
uint32_t fileDataId = 0;
|
||||||
|
const auto parsed = std::from_chars(idText.data(), idText.data() + idText.size(), fileDataId);
|
||||||
|
if (parsed.ec != std::errc{} || parsed.ptr != idText.data() + idText.size() ||
|
||||||
|
fileDataId == 0 || pathText.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string path(pathText);
|
||||||
|
for (char& c : path) if (c == '/') c = '\\';
|
||||||
|
g_paths[fileDataId] = std::move(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_api && g_api->Log)
|
||||||
|
g_api->Log(WXL_LOG_INFO, "MoonWellFdid", "loaded %zu custom FileDataID path(s)",
|
||||||
|
g_paths.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ResolveCustom(uint32_t fileDataId)
|
||||||
|
{
|
||||||
|
std::call_once(g_loadOnce, &Load);
|
||||||
|
const auto found = g_paths.find(fileDataId);
|
||||||
|
return found == g_paths.end() ? nullptr : found->second.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* __cdecl ResolveTexture(uint32_t fileDataId)
|
||||||
|
{
|
||||||
|
if (const char* custom = ResolveCustom(fileDataId)) return custom;
|
||||||
|
return g_resolveTexture ? g_resolveTexture(fileDataId) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* __cdecl ResolveModel(uint32_t fileDataId)
|
||||||
|
{
|
||||||
|
if (const char* custom = ResolveCustom(fileDataId)) return custom;
|
||||||
|
return g_resolveModel ? g_resolveModel(fileDataId) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PatchResolver(WXL_FdidApi* fdid)
|
||||||
|
{
|
||||||
|
if (!fdid || fdid->apiVersion != WXL_FDID_API_VERSION) return false;
|
||||||
|
g_resolveTexture = fdid->ResolveTexture;
|
||||||
|
g_resolveModel = fdid->ResolveModel;
|
||||||
|
|
||||||
|
DWORD oldProtection = 0;
|
||||||
|
if (!VirtualProtect(fdid, sizeof(*fdid), PAGE_READWRITE, &oldProtection)) return false;
|
||||||
|
fdid->ResolveTexture = &ResolveTexture;
|
||||||
|
fdid->ResolveModel = &ResolveModel;
|
||||||
|
DWORD ignored = 0;
|
||||||
|
VirtualProtect(fdid, sizeof(*fdid), oldProtection, &ignored);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const WXL_PluginInfo* __cdecl WXL_Query(void)
|
||||||
|
{
|
||||||
|
static const WXL_PluginInfo info = {
|
||||||
|
sizeof(WXL_PluginInfo), WXL_API_VERSION, "MoonWellFdid", 1, WXL_CLIENT_BUILD,
|
||||||
|
};
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl WXL_Load(const WXL_Api* api)
|
||||||
|
{
|
||||||
|
if (!api || api->apiVersion != WXL_API_VERSION) return 0;
|
||||||
|
moonwell::fdid::g_api = api;
|
||||||
|
auto* fdid = static_cast<WXL_FdidApi*>(api->GetInterface("wxl.fdid", WXL_FDID_API_VERSION));
|
||||||
|
if (!moonwell::fdid::PatchResolver(fdid))
|
||||||
|
{
|
||||||
|
api->Log(WXL_LOG_ERROR, "MoonWellFdid", "wxl.fdid v1 is unavailable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
api->Log(WXL_LOG_INFO, "MoonWellFdid", "custom FileDataID overlay installed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// MoonWell's specific-archive fallback, kept outside the WarcraftXL core.
|
||||||
|
|
||||||
|
#include "wxl/PluginApi.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const WXL_Api* g_api = nullptr;
|
||||||
|
using FileOpenFn = int(__stdcall*)(void* archive, const char* name, uint32_t flags, void** out);
|
||||||
|
FileOpenFn g_nextOpen = nullptr;
|
||||||
|
std::atomic<uint32_t> g_logCount{0};
|
||||||
|
|
||||||
|
int __stdcall FileOpenHook(void* archive, const char* name, uint32_t flags, void** out)
|
||||||
|
{
|
||||||
|
if (!g_nextOpen) return 0;
|
||||||
|
|
||||||
|
const int nativeResult = g_nextOpen(archive, name, flags, out);
|
||||||
|
if (nativeResult || archive == nullptr || !name || !*name) return nativeResult;
|
||||||
|
|
||||||
|
// A dependency requested through one concrete MPQ may live in a higher-priority loose
|
||||||
|
// Patch-*.MPQ directory. Retry only after that exact archive misses, using the client's
|
||||||
|
// normal global search path. This is the MoonWell-only behavior that used to patch core.
|
||||||
|
if (out) *out = nullptr;
|
||||||
|
const int fallbackResult = g_nextOpen(nullptr, name, flags, out);
|
||||||
|
if (fallbackResult && g_api && g_api->Log)
|
||||||
|
{
|
||||||
|
const uint32_t index = g_logCount.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
if (index < 32)
|
||||||
|
g_api->Log(WXL_LOG_INFO, "MoonWellStorageFallback",
|
||||||
|
"specific archive miss resolved globally: '%s'", name);
|
||||||
|
}
|
||||||
|
return fallbackResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const WXL_PluginInfo* __cdecl WXL_Query(void)
|
||||||
|
{
|
||||||
|
static const WXL_PluginInfo info = {
|
||||||
|
sizeof(WXL_PluginInfo), WXL_API_VERSION, "MoonWellStorageFallback", 1,
|
||||||
|
WXL_CLIENT_BUILD,
|
||||||
|
};
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl WXL_Load(const WXL_Api* api)
|
||||||
|
{
|
||||||
|
if (!api || api->apiVersion != WXL_API_VERSION || !api->HookAttachByName) return 0;
|
||||||
|
g_api = api;
|
||||||
|
const int installed = api->HookAttachByName(
|
||||||
|
"Io.FileOpen", reinterpret_cast<void*>(&FileOpenHook),
|
||||||
|
reinterpret_cast<void**>(&g_nextOpen), WXL_HOOK_DEFAULT_PRIORITY);
|
||||||
|
api->Log(installed ? WXL_LOG_INFO : WXL_LOG_ERROR, "MoonWellStorageFallback", "%s",
|
||||||
|
installed ? "specific-archive fallback installed" : "Io.FileOpen hook failed");
|
||||||
|
return installed;
|
||||||
|
}
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
// FileDataID resolver for selected retail assets shipped in MoonWell patches.
|
|
||||||
|
|
||||||
#include "Host.hpp"
|
|
||||||
#include "core/Logger.hpp"
|
|
||||||
#include "mpq/MpqStore.hpp"
|
|
||||||
|
|
||||||
#include <charconv>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
#include <system_error>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace moonwell::host
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
constexpr std::string_view kFileDataMap = "WXLFileData.csv";
|
|
||||||
|
|
||||||
std::once_flag g_loadOnce;
|
|
||||||
std::unordered_map<uint32_t, std::string> g_paths;
|
|
||||||
|
|
||||||
std::string_view Trim(std::string_view value)
|
|
||||||
{
|
|
||||||
while (!value.empty() && (value.front() == ' ' || value.front() == '\t' ||
|
|
||||||
value.front() == '\r' || value.front() == '\n'))
|
|
||||||
value.remove_prefix(1);
|
|
||||||
while (!value.empty() && (value.back() == ' ' || value.back() == '\t' ||
|
|
||||||
value.back() == '\r' || value.back() == '\n'))
|
|
||||||
value.remove_suffix(1);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Load()
|
|
||||||
{
|
|
||||||
const std::string root = wxl::host::ClientRoot();
|
|
||||||
wxl::host::mpq::MpqStore store;
|
|
||||||
std::vector<uint8_t> bytes;
|
|
||||||
if (root.empty() || !store.Mount(root) || !store.ReadAll(kFileDataMap, bytes))
|
|
||||||
{
|
|
||||||
WLOG_WARN("moonwell: FileDataID map '%.*s' was not found",
|
|
||||||
int(kFileDataMap.size()), kFileDataMap.data());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string_view text(reinterpret_cast<const char*>(bytes.data()), bytes.size());
|
|
||||||
size_t lineStart = 0;
|
|
||||||
while (lineStart < text.size())
|
|
||||||
{
|
|
||||||
size_t lineEnd = text.find('\n', lineStart);
|
|
||||||
if (lineEnd == std::string_view::npos) lineEnd = text.size();
|
|
||||||
std::string_view line = Trim(text.substr(lineStart, lineEnd - lineStart));
|
|
||||||
lineStart = lineEnd + 1;
|
|
||||||
|
|
||||||
if (line.empty() || line.front() == '#') continue;
|
|
||||||
const size_t comma = line.find(',');
|
|
||||||
if (comma == std::string_view::npos) continue;
|
|
||||||
|
|
||||||
const std::string_view idText = Trim(line.substr(0, comma));
|
|
||||||
std::string_view pathText = Trim(line.substr(comma + 1));
|
|
||||||
uint32_t fileDataId = 0;
|
|
||||||
const auto parsed = std::from_chars(idText.data(), idText.data() + idText.size(), fileDataId);
|
|
||||||
if (parsed.ec != std::errc{} || parsed.ptr != idText.data() + idText.size() ||
|
|
||||||
fileDataId == 0 || pathText.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string path(pathText);
|
|
||||||
for (char& c : path) if (c == '/') c = '\\';
|
|
||||||
g_paths[fileDataId] = std::move(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
WLOG_INFO("moonwell: loaded %zu FileDataID path(s) from %.*s",
|
|
||||||
g_paths.size(), int(kFileDataMap.size()), kFileDataMap.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Resolve(uint32_t fileDataId, std::string& outPath)
|
|
||||||
{
|
|
||||||
std::call_once(g_loadOnce, &Load);
|
|
||||||
const auto found = g_paths.find(fileDataId);
|
|
||||||
if (found == g_paths.end()) return false;
|
|
||||||
outPath = found->second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Registrar
|
|
||||||
{
|
|
||||||
Registrar() { wxl::host::RegisterResolver("moonwell-filedata", &Resolve); }
|
|
||||||
};
|
|
||||||
|
|
||||||
Registrar g_registrar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,28 +5,71 @@
|
|||||||
// changes are verified and applied to the process image during WarcraftXL's
|
// changes are verified and applied to the process image during WarcraftXL's
|
||||||
// boot phase, before GlueXML is loaded.
|
// boot phase, before GlueXML is loaded.
|
||||||
|
|
||||||
#include "core/Logger.hpp"
|
#include "game/Script.hpp"
|
||||||
#include "core/Hook.hpp"
|
#include "wxl/PluginApi.h"
|
||||||
#include "core/Mem.hpp"
|
#include "SpellOverrides.hpp"
|
||||||
#include "runtime/LuaBindings.hpp"
|
|
||||||
#include "runtime/ModuleInstall.hpp"
|
|
||||||
#include "offsets/engine/Gx.hpp"
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
namespace moonwell
|
namespace moonwell
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
const WXL_Api* g_api = nullptr;
|
||||||
|
|
||||||
|
void Log(int level, const char* format, ...)
|
||||||
|
{
|
||||||
|
if (!g_api || !g_api->Log) return;
|
||||||
|
char message[1024]{};
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsnprintf_s(message, sizeof(message), _TRUNCATE, format, args);
|
||||||
|
va_end(args);
|
||||||
|
g_api->Log(level, "MoonWell", "%s", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WLOG_INFO(...) Log(WXL_LOG_INFO, __VA_ARGS__)
|
||||||
|
#define WLOG_ERROR(...) Log(WXL_LOG_ERROR, __VA_ARGS__)
|
||||||
|
|
||||||
|
bool PatchMemory(void* destination, const void* source, size_t size)
|
||||||
|
{
|
||||||
|
DWORD oldProtection = 0;
|
||||||
|
if (!VirtualProtect(destination, size, PAGE_EXECUTE_READWRITE, &oldProtection))
|
||||||
|
return false;
|
||||||
|
std::memcpy(destination, source, size);
|
||||||
|
FlushInstructionCache(GetCurrentProcess(), destination, size);
|
||||||
|
DWORD ignored = 0;
|
||||||
|
VirtualProtect(destination, size, oldProtection, &ignored);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Fn>
|
||||||
|
bool Hook(const char* name, uintptr_t address, Fn* detour, Fn** original)
|
||||||
|
{
|
||||||
|
return g_api && g_api->HookAttach && g_api->HookAttach(
|
||||||
|
name, address, reinterpret_cast<void*>(detour),
|
||||||
|
reinterpret_cast<void**>(original), WXL_HOOK_DEFAULT_PRIORITY) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Fn>
|
||||||
|
bool HookByName(const char* point, Fn* detour, Fn** original)
|
||||||
|
{
|
||||||
|
return g_api && g_api->HookAttachByName && g_api->HookAttachByName(
|
||||||
|
point, reinterpret_cast<void*>(detour), reinterpret_cast<void**>(original),
|
||||||
|
WXL_HOOK_DEFAULT_PRIORITY) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr uint32_t kTraitorFlag = 0x40000000u;
|
constexpr uint32_t kTraitorFlag = 0x40000000u;
|
||||||
bool g_loginCharacterIsTraitor = false;
|
bool g_loginCharacterIsTraitor = false;
|
||||||
|
|
||||||
using GxSetProjectionFn = wxl::offsets::engine::gx::GxSetProjectionFn;
|
using GxSetProjectionFn = void(__fastcall*)(void* self, void* edx, const void* projection);
|
||||||
GxSetProjectionFn g_nextSetProjection = nullptr;
|
GxSetProjectionFn g_nextSetProjection = nullptr;
|
||||||
|
|
||||||
// FrameXML's stock SetCreature only accepts a creature entry and waits
|
// FrameXML's stock SetCreature only accepts a creature entry and waits
|
||||||
@@ -64,10 +107,10 @@ namespace moonwell
|
|||||||
int __cdecl SetCreatureDisplayInfoHook(void* state)
|
int __cdecl SetCreatureDisplayInfoHook(void* state)
|
||||||
{
|
{
|
||||||
const int result = g_nextSetCreature ? g_nextSetCreature(state) : 0;
|
const int result = g_nextSetCreature ? g_nextSetCreature(state) : 0;
|
||||||
if (!state || !wxl::runtime::lua::IsNumber(state, 3))
|
if (!state || !wxl::game::script::IsNumber(state, 3))
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
const double requestedDisplayInfo = wxl::runtime::lua::ToNumber(state, 3);
|
const double requestedDisplayInfo = wxl::game::script::ToNumber(state, 3);
|
||||||
if (requestedDisplayInfo <= 0.0 || requestedDisplayInfo > 4294967295.0)
|
if (requestedDisplayInfo <= 0.0 || requestedDisplayInfo > 4294967295.0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -102,8 +145,8 @@ namespace moonwell
|
|||||||
|
|
||||||
void InstallEncounterJournalModelPreview()
|
void InstallEncounterJournalModelPreview()
|
||||||
{
|
{
|
||||||
if (!wxl::core::hook::Install("MoonWellSetCreatureDisplayInfo", kSetCreature,
|
if (!Hook("MoonWellSetCreatureDisplayInfo", kSetCreature,
|
||||||
&SetCreatureDisplayInfoHook, &g_nextSetCreature))
|
&SetCreatureDisplayInfoHook, &g_nextSetCreature))
|
||||||
{
|
{
|
||||||
WLOG_ERROR("moonwell: encounter journal model hook installation failed");
|
WLOG_ERROR("moonwell: encounter journal model hook installation failed");
|
||||||
return;
|
return;
|
||||||
@@ -151,14 +194,14 @@ namespace moonwell
|
|||||||
|
|
||||||
int __cdecl SetCharacterCreateCamera(void* state)
|
int __cdecl SetCharacterCreateCamera(void* state)
|
||||||
{
|
{
|
||||||
const bool enabled = state && wxl::runtime::lua::IsNumber(state, 1)
|
const bool enabled = state && wxl::game::script::IsNumber(state, 1)
|
||||||
&& wxl::runtime::lua::ToNumber(state, 1) != 0.0;
|
&& wxl::game::script::ToNumber(state, 1) != 0.0;
|
||||||
const float faceZoom = state && wxl::runtime::lua::IsNumber(state, 2)
|
const float faceZoom = state && wxl::game::script::IsNumber(state, 2)
|
||||||
? static_cast<float>(wxl::runtime::lua::ToNumber(state, 2)) : 2.0f;
|
? static_cast<float>(wxl::game::script::ToNumber(state, 2)) : 2.0f;
|
||||||
const float faceVerticalOffset = state && wxl::runtime::lua::IsNumber(state, 3)
|
const float faceVerticalOffset = state && wxl::game::script::IsNumber(state, 3)
|
||||||
? static_cast<float>(wxl::runtime::lua::ToNumber(state, 3)) : -0.65f;
|
? static_cast<float>(wxl::game::script::ToNumber(state, 3)) : -0.65f;
|
||||||
double requestedDuration = state && wxl::runtime::lua::IsNumber(state, 4)
|
double requestedDuration = state && wxl::game::script::IsNumber(state, 4)
|
||||||
? wxl::runtime::lua::ToNumber(state, 4) : 500.0;
|
? wxl::game::script::ToNumber(state, 4) : 500.0;
|
||||||
if (requestedDuration < 0.0) requestedDuration = 0.0;
|
if (requestedDuration < 0.0) requestedDuration = 0.0;
|
||||||
if (requestedDuration > 2000.0) requestedDuration = 2000.0;
|
if (requestedDuration > 2000.0) requestedDuration = 2000.0;
|
||||||
|
|
||||||
@@ -202,15 +245,16 @@ namespace moonwell
|
|||||||
|
|
||||||
void InstallCharacterCreateCamera()
|
void InstallCharacterCreateCamera()
|
||||||
{
|
{
|
||||||
namespace gx = wxl::offsets::engine::gx;
|
constexpr uintptr_t kGxDeviceVTable = 0x00A2E718;
|
||||||
void** vtable = reinterpret_cast<void**>(gx::kGxDeviceVTable);
|
constexpr unsigned kGxSetProjectionSlot = 0xA0 / 4;
|
||||||
void** slot = &vtable[gx::kGxSetProjectionSlot];
|
void** vtable = reinterpret_cast<void**>(kGxDeviceVTable);
|
||||||
|
void** slot = &vtable[kGxSetProjectionSlot];
|
||||||
if (*slot == reinterpret_cast<void*>(&CharacterCreateProjectionHook))
|
if (*slot == reinterpret_cast<void*>(&CharacterCreateProjectionHook))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_nextSetProjection = reinterpret_cast<GxSetProjectionFn>(*slot);
|
g_nextSetProjection = reinterpret_cast<GxSetProjectionFn>(*slot);
|
||||||
void* replacement = reinterpret_cast<void*>(&CharacterCreateProjectionHook);
|
void* replacement = reinterpret_cast<void*>(&CharacterCreateProjectionHook);
|
||||||
if (!g_nextSetProjection || !wxl::core::mem::Patch(slot, &replacement, sizeof(replacement)))
|
if (!g_nextSetProjection || !PatchMemory(slot, &replacement, sizeof(replacement)))
|
||||||
{
|
{
|
||||||
g_nextSetProjection = nullptr;
|
g_nextSetProjection = nullptr;
|
||||||
WLOG_ERROR("moonwell: character-create projection hook installation failed");
|
WLOG_ERROR("moonwell: character-create projection hook installation failed");
|
||||||
@@ -222,17 +266,17 @@ namespace moonwell
|
|||||||
int __cdecl SetLoginCharacterFlags(void* state)
|
int __cdecl SetLoginCharacterFlags(void* state)
|
||||||
{
|
{
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
if (state && wxl::runtime::lua::IsNumber(state, 1))
|
if (state && wxl::game::script::IsNumber(state, 1))
|
||||||
flags = static_cast<uint32_t>(wxl::runtime::lua::ToNumber(state, 1));
|
flags = static_cast<uint32_t>(wxl::game::script::ToNumber(state, 1));
|
||||||
|
|
||||||
g_loginCharacterIsTraitor = (flags & kTraitorFlag) != 0;
|
g_loginCharacterIsTraitor = (flags & kTraitorFlag) != 0;
|
||||||
wxl::runtime::lua::PushBoolean(state, g_loginCharacterIsTraitor ? 1 : 0);
|
wxl::game::script::PushBoolean(state, g_loginCharacterIsTraitor);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __cdecl IsTraitor(void* state)
|
int __cdecl IsTraitor(void* state)
|
||||||
{
|
{
|
||||||
wxl::runtime::lua::PushBoolean(state, g_loginCharacterIsTraitor ? 1 : 0);
|
wxl::game::script::PushBoolean(state, g_loginCharacterIsTraitor);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +303,7 @@ namespace moonwell
|
|||||||
name, reinterpret_cast<void*>(address));
|
name, reinterpret_cast<void*>(address));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!wxl::core::mem::Patch(reinterpret_cast<void*>(address), replacement.data(), N))
|
if (!PatchMemory(reinterpret_cast<void*>(address), replacement.data(), N))
|
||||||
{
|
{
|
||||||
WLOG_ERROR("moonwell: '%s' patch failed at %p", name,
|
WLOG_ERROR("moonwell: '%s' patch failed at %p", name,
|
||||||
reinterpret_cast<void*>(address));
|
reinterpret_cast<void*>(address));
|
||||||
@@ -371,7 +415,7 @@ namespace moonwell
|
|||||||
const auto caveRel = static_cast<int32_t>(reinterpret_cast<uintptr_t>(cave) -
|
const auto caveRel = static_cast<int32_t>(reinterpret_cast<uintptr_t>(cave) -
|
||||||
(patchAddress + jump.size()));
|
(patchAddress + jump.size()));
|
||||||
std::memcpy(jump.data() + 1, &caveRel, sizeof(caveRel));
|
std::memcpy(jump.data() + 1, &caveRel, sizeof(caveRel));
|
||||||
if (!wxl::core::mem::Patch(reinterpret_cast<void*>(patchAddress), jump.data(), jump.size()))
|
if (!PatchMemory(reinterpret_cast<void*>(patchAddress), jump.data(), jump.size()))
|
||||||
{
|
{
|
||||||
VirtualFree(cave, 0, MEM_RELEASE);
|
VirtualFree(cave, 0, MEM_RELEASE);
|
||||||
WLOG_ERROR("moonwell: GetCharacterInfo jump patch failed");
|
WLOG_ERROR("moonwell: GetCharacterInfo jump patch failed");
|
||||||
@@ -390,40 +434,84 @@ namespace moonwell
|
|||||||
WLOG_ERROR("moonwell: compatibility module incomplete; see mismatches above");
|
WLOG_ERROR("moonwell: compatibility module incomplete; see mismatches above");
|
||||||
else
|
else
|
||||||
WLOG_INFO("moonwell: compatibility module ready (stock Wow.exe remains untouched)");
|
WLOG_INFO("moonwell: compatibility module ready (stock Wow.exe remains untouched)");
|
||||||
wxl::core::log::Flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI FlushRuntimeLog(LPVOID)
|
using RegisterFunctionFn = void(__cdecl*)(const char*, wxl::game::script::Function);
|
||||||
|
using ValidateCallbackFn = void(__cdecl*)(uintptr_t);
|
||||||
|
using GetContextFn = void*(__cdecl*)();
|
||||||
|
RegisterFunctionFn g_nextRegisterFunction = nullptr;
|
||||||
|
ValidateCallbackFn g_nextValidateCallback = nullptr;
|
||||||
|
void* g_registeredState = nullptr;
|
||||||
|
bool g_registeringMoonWell = false;
|
||||||
|
|
||||||
|
bool IsMoonWellCallback(uintptr_t callback)
|
||||||
{
|
{
|
||||||
// Let the remainder of RunAll() and the core-ready line reach the
|
return callback == reinterpret_cast<uintptr_t>(&SetLoginCharacterFlags)
|
||||||
// shared buffered logger, then make startup diagnostics durable.
|
|| callback == reinterpret_cast<uintptr_t>(&IsTraitor)
|
||||||
Sleep(1000);
|
|| callback == reinterpret_cast<uintptr_t>(&SetCharacterCreateCamera);
|
||||||
wxl::core::log::Flush();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallRuntimeLogFlush()
|
void __cdecl ValidateCallbackHook(uintptr_t callback)
|
||||||
{
|
{
|
||||||
HANDLE thread = CreateThread(nullptr, 0, &FlushRuntimeLog, nullptr, 0, nullptr);
|
if (!IsMoonWellCallback(callback) && g_nextValidateCallback)
|
||||||
if (thread) CloseHandle(thread);
|
g_nextValidateCallback(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Registration
|
void RegisterLuaFunctionsForCurrentState()
|
||||||
{
|
{
|
||||||
Registration()
|
if (!g_nextRegisterFunction || g_registeringMoonWell) return;
|
||||||
{
|
constexpr uintptr_t kGetContext = 0x00817DB0;
|
||||||
wxl::runtime::lua::RegisterFunction(
|
void* state = reinterpret_cast<GetContextFn>(kGetContext)();
|
||||||
"MoonWellSetLoginCharacterFlags", &SetLoginCharacterFlags);
|
if (!state || state == g_registeredState) return;
|
||||||
wxl::runtime::lua::RegisterFunction("MoonWellIsTraitor", &IsTraitor);
|
|
||||||
wxl::runtime::lua::RegisterFunction(
|
g_registeringMoonWell = true;
|
||||||
"MoonWellSetCharacterCreateCamera", &SetCharacterCreateCamera);
|
g_nextRegisterFunction("MoonWellSetLoginCharacterFlags", &SetLoginCharacterFlags);
|
||||||
wxl::runtime::modules::RegisterBoot("moonwell", &InstallBoot);
|
g_nextRegisterFunction("MoonWellIsTraitor", &IsTraitor);
|
||||||
wxl::runtime::modules::Register(
|
g_nextRegisterFunction("MoonWellSetCharacterCreateCamera", &SetCharacterCreateCamera);
|
||||||
"moonwell-character-create-camera", &InstallCharacterCreateCamera);
|
g_registeringMoonWell = false;
|
||||||
wxl::runtime::modules::Register(
|
g_registeredState = state;
|
||||||
"moonwell-encounter-journal-models", &InstallEncounterJournalModelPreview);
|
WLOG_INFO("moonwell: Lua functions registered for state %p", state);
|
||||||
wxl::runtime::modules::Register("moonwell-log-flush", &InstallRuntimeLogFlush);
|
}
|
||||||
}
|
|
||||||
} g_registration;
|
void __cdecl RegisterFunctionHook(const char* name, wxl::game::script::Function function)
|
||||||
|
{
|
||||||
|
if (g_nextRegisterFunction) g_nextRegisterFunction(name, function);
|
||||||
|
RegisterLuaFunctionsForCurrentState();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstallLuaBridge()
|
||||||
|
{
|
||||||
|
const bool validator = HookByName("Lua.ValidateFunctionPointer", &ValidateCallbackHook,
|
||||||
|
&g_nextValidateCallback);
|
||||||
|
const bool registrar = HookByName("Lua.RegisterFunction", &RegisterFunctionHook,
|
||||||
|
&g_nextRegisterFunction);
|
||||||
|
if (!validator || !registrar)
|
||||||
|
WLOG_ERROR("moonwell: Lua bridge hook installation failed");
|
||||||
|
return validator && registrar;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WXL_PluginInfo* __cdecl WXL_Query(void)
|
||||||
|
{
|
||||||
|
static const WXL_PluginInfo info = {
|
||||||
|
sizeof(WXL_PluginInfo), WXL_API_VERSION, "MoonWell", 1, WXL_CLIENT_BUILD,
|
||||||
|
};
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl WXL_Load(const WXL_Api* api)
|
||||||
|
{
|
||||||
|
if (!api || api->apiVersion != WXL_API_VERSION) return 0;
|
||||||
|
moonwell::g_api = api;
|
||||||
|
|
||||||
|
moonwell::InstallBoot();
|
||||||
|
const bool lua = moonwell::InstallLuaBridge();
|
||||||
|
moonwell::InstallCharacterCreateCamera();
|
||||||
|
moonwell::InstallEncounterJournalModelPreview();
|
||||||
|
const bool spells = moonwell::spells::Install(api);
|
||||||
|
const bool ready = lua && spells;
|
||||||
|
api->Log(ready ? WXL_LOG_INFO : WXL_LOG_ERROR, "MoonWell", "%s",
|
||||||
|
ready ? "MoonWell extension loaded" : "MoonWell extension loaded with errors");
|
||||||
|
return ready ? 1 : 0;
|
||||||
|
}
|
||||||
|
|||||||
+72
-26
@@ -1,9 +1,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Appends compact MoonWell spell overrides to the stock 3.3.5 DBCs at open time.
|
// Appends compact MoonWell spell overrides to stock 3.3.5 DBC bytes.
|
||||||
|
|
||||||
#include "Host.hpp"
|
#include "game/Io.hpp"
|
||||||
#include "core/Logger.hpp"
|
#include "wxl/PluginApi.h"
|
||||||
#include "mpq/MpqStore.hpp"
|
#include "wxl/StorageApi.h"
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace moonwell::host
|
namespace moonwell::spells
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -38,8 +38,34 @@ namespace moonwell::host
|
|||||||
|
|
||||||
std::once_flag g_loadOnce;
|
std::once_flag g_loadOnce;
|
||||||
bool g_ready = false;
|
bool g_ready = false;
|
||||||
std::vector<uint8_t> g_spellDbc;
|
const WXL_Api* g_api = nullptr;
|
||||||
std::vector<uint8_t> g_skillDbc;
|
std::vector<Override> g_overrides;
|
||||||
|
|
||||||
|
void Log(int level, const char* message)
|
||||||
|
{
|
||||||
|
if (g_api && g_api->Log) g_api->Log(level, "MoonWellSpells", "%s", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadAll(const char* path, std::vector<uint8_t>& out)
|
||||||
|
{
|
||||||
|
void* handle = nullptr;
|
||||||
|
if (!wxl::game::io::FileOpen(path, wxl::game::io::kOpenWholeFile, &handle) || !handle)
|
||||||
|
return false;
|
||||||
|
uint32_t high = 0;
|
||||||
|
const uint32_t size = wxl::game::io::FileSize(handle, &high);
|
||||||
|
if (high != 0)
|
||||||
|
{
|
||||||
|
wxl::game::io::FileClose(handle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.resize(size);
|
||||||
|
uint32_t read = 0;
|
||||||
|
const bool ok = (size == 0 || wxl::game::io::FileRead(handle, out.data(), size, &read))
|
||||||
|
&& read == size;
|
||||||
|
wxl::game::io::FileClose(handle);
|
||||||
|
if (!ok) out.clear();
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t ReadU32(const uint8_t* data)
|
uint32_t ReadU32(const uint8_t* data)
|
||||||
{
|
{
|
||||||
@@ -226,39 +252,59 @@ namespace moonwell::host
|
|||||||
|
|
||||||
void Load()
|
void Load()
|
||||||
{
|
{
|
||||||
const std::string root = wxl::host::ClientRoot();
|
std::vector<uint8_t> overrideBytes;
|
||||||
wxl::host::mpq::MpqStore store;
|
if (!ReadAll(kOverridesPath.data(), overrideBytes))
|
||||||
std::vector<uint8_t> overrideBytes, spellBase, skillBase;
|
|
||||||
if (root.empty() || !store.Mount(root) || !store.ReadAll(kOverridesPath, overrideBytes))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<Override> overrides;
|
if (!ParseOverrides(overrideBytes, g_overrides))
|
||||||
if (!ParseOverrides(overrideBytes, overrides) ||
|
|
||||||
!store.ReadAll(kSpellPath, spellBase) || !store.ReadAll(kSkillPath, skillBase) ||
|
|
||||||
!BuildSpellDbc(spellBase, overrides, g_spellDbc) ||
|
|
||||||
!BuildSkillDbc(skillBase, overrides, g_skillDbc))
|
|
||||||
{
|
{
|
||||||
WLOG_ERROR("moonwell-spells: failed to build custom companion DBCs");
|
Log(WXL_LOG_ERROR, "failed to parse WXLSpellOverrides.tsv");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_ready = true;
|
g_ready = true;
|
||||||
WLOG_INFO("moonwell-spells: appended %zu companion spell(s)", overrides.size());
|
if (g_api && g_api->Log)
|
||||||
|
g_api->Log(WXL_LOG_INFO, "MoonWellSpells", "loaded %zu companion spell override(s)",
|
||||||
|
g_overrides.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Provide(std::string_view name, std::vector<uint8_t>& out)
|
int __cdecl Transform(const char* rawName, const uint8_t* raw, uint32_t rawLen,
|
||||||
|
const WXL_ByteSink* sink)
|
||||||
{
|
{
|
||||||
|
if (!rawName || !raw || !sink || !sink->Write) return 0;
|
||||||
|
const std::string_view name(rawName);
|
||||||
if (!SamePath(name, kSpellPath) && !SamePath(name, kSkillPath)) return false;
|
if (!SamePath(name, kSpellPath) && !SamePath(name, kSkillPath)) return false;
|
||||||
std::call_once(g_loadOnce, &Load);
|
std::call_once(g_loadOnce, &Load);
|
||||||
if (!g_ready) return false;
|
if (!g_ready) return false;
|
||||||
out = SamePath(name, kSpellPath) ? g_spellDbc : g_skillDbc;
|
|
||||||
return true;
|
const std::vector<uint8_t> base(raw, raw + rawLen);
|
||||||
|
std::vector<uint8_t> out;
|
||||||
|
const bool built = SamePath(name, kSpellPath)
|
||||||
|
? BuildSpellDbc(base, g_overrides, out)
|
||||||
|
: BuildSkillDbc(base, g_overrides, out);
|
||||||
|
if (!built)
|
||||||
|
{
|
||||||
|
Log(WXL_LOG_ERROR, "failed to build custom companion DBC");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sink->Write(sink->ctx, out.data(), static_cast<uint32_t>(out.size()));
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Registrar
|
bool Install(const WXL_Api* api)
|
||||||
|
{
|
||||||
|
g_api = api;
|
||||||
|
if (!api || !api->GetInterface) return false;
|
||||||
|
auto* storage = static_cast<WXL_StorageApi*>(
|
||||||
|
api->GetInterface("wxl.storage", WXL_STORAGE_API_VERSION));
|
||||||
|
if (!storage || storage->apiVersion != WXL_STORAGE_API_VERSION ||
|
||||||
|
!storage->RegisterClientTransform)
|
||||||
{
|
{
|
||||||
Registrar() { wxl::host::RegisterProvider("moonwell-companion-spells", &Provide); }
|
Log(WXL_LOG_ERROR, "wxl.storage v1 is unavailable");
|
||||||
};
|
return false;
|
||||||
|
}
|
||||||
Registrar g_registrar;
|
storage->RegisterClientTransform(".dbc", &Transform);
|
||||||
|
Log(WXL_LOG_INFO, "DBC override transform registered");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct WXL_Api;
|
||||||
|
|
||||||
|
namespace moonwell::spells
|
||||||
|
{
|
||||||
|
bool Install(const WXL_Api* api);
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
file(GLOB_RECURSE WXL_EXT_SHARED_SRC CONFIGURE_DEPENDS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/engine/assets/shared/textures/blp/*.cpp")
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// WarcraftXL 1.1 BLP transform extension.
|
||||||
|
|
||||||
|
#include "engine/assets/shared/textures/blp/BlpTranscode.hpp"
|
||||||
|
#include "wxl/ModernBlpApi.h"
|
||||||
|
#include "wxl/PluginApi.h"
|
||||||
|
#include "wxl/StorageApi.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <span>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const WXL_Api* g_api = nullptr;
|
||||||
|
constexpr uint32_t kMaxTextureEdge = 1024;
|
||||||
|
|
||||||
|
int __cdecl Transcode(const char* name, const uint8_t* raw, uint32_t rawLen,
|
||||||
|
const WXL_ByteSink* sink)
|
||||||
|
{
|
||||||
|
if (!raw || !sink || !sink->Write) return 0;
|
||||||
|
namespace blp = wxl::modern::assets::textures::blp;
|
||||||
|
|
||||||
|
const std::span<const uint8_t> input(raw, rawLen);
|
||||||
|
std::vector<uint8_t> capped;
|
||||||
|
const bool didCap = blp::CapBlpMips(input, capped, kMaxTextureEdge);
|
||||||
|
const std::span<const uint8_t> source = didCap
|
||||||
|
? std::span<const uint8_t>(capped.data(), capped.size()) : input;
|
||||||
|
|
||||||
|
std::vector<uint8_t> transcoded;
|
||||||
|
if (blp::TranscodeBlp(source, transcoded))
|
||||||
|
{
|
||||||
|
sink->Write(sink->ctx, transcoded.data(), static_cast<uint32_t>(transcoded.size()));
|
||||||
|
if (g_api && g_api->Log)
|
||||||
|
g_api->Log(WXL_LOG_DEBUG, "wxl-modern-blp", "%s%s BGRA->DXT5",
|
||||||
|
name ? name : "?", didCap ? " capped" : "");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!didCap) return 0;
|
||||||
|
|
||||||
|
sink->Write(sink->ctx, capped.data(), static_cast<uint32_t>(capped.size()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WXL_ModernBlpApi g_blpApi = {
|
||||||
|
sizeof(WXL_ModernBlpApi), WXL_MODERN_BLP_API_VERSION, &Transcode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const WXL_PluginInfo* __cdecl WXL_Query(void)
|
||||||
|
{
|
||||||
|
static const WXL_PluginInfo info = {
|
||||||
|
sizeof(WXL_PluginInfo), WXL_API_VERSION, "wxl-modern-blp", 1, WXL_CLIENT_BUILD,
|
||||||
|
};
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl WXL_Load(const WXL_Api* api)
|
||||||
|
{
|
||||||
|
if (!api || api->apiVersion != WXL_API_VERSION) return 0;
|
||||||
|
g_api = api;
|
||||||
|
auto* storage = static_cast<WXL_StorageApi*>(
|
||||||
|
api->GetInterface("wxl.storage", WXL_STORAGE_API_VERSION));
|
||||||
|
if (!storage || storage->apiVersion != WXL_STORAGE_API_VERSION ||
|
||||||
|
!storage->RegisterClientTransform)
|
||||||
|
{
|
||||||
|
api->Log(WXL_LOG_ERROR, "wxl-modern-blp", "wxl.storage v1 is unavailable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage->RegisterClientTransform(".blp", &Transcode);
|
||||||
|
api->PublishInterface("wxl.modern-blp", WXL_MODERN_BLP_API_VERSION,
|
||||||
|
const_cast<WXL_ModernBlpApi*>(&g_blpApi));
|
||||||
|
api->Log(WXL_LOG_INFO, "wxl-modern-blp", "BLP transcode and mip cap active");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -84,7 +84,7 @@ function Stop-WowRuntime {
|
|||||||
param([Parameter(Mandatory=$true)][string]$ClientPath)
|
param([Parameter(Mandatory=$true)][string]$ClientPath)
|
||||||
|
|
||||||
$clientRoot = [System.IO.Path]::GetFullPath($ClientPath).TrimEnd('\') + '\'
|
$clientRoot = [System.IO.Path]::GetFullPath($ClientPath).TrimEnd('\') + '\'
|
||||||
$runtimeProcesses = @(Get-Process -Name "Wow", "WarcraftXLHost" -ErrorAction SilentlyContinue | Where-Object {
|
$runtimeProcesses = @(Get-Process -Name "Wow" -ErrorAction SilentlyContinue | Where-Object {
|
||||||
try {
|
try {
|
||||||
$_.Path -and $_.Path.StartsWith($clientRoot, [System.StringComparison]::OrdinalIgnoreCase)
|
$_.Path -and $_.Path.StartsWith($clientRoot, [System.StringComparison]::OrdinalIgnoreCase)
|
||||||
} catch {
|
} catch {
|
||||||
@@ -96,7 +96,7 @@ function Stop-WowRuntime {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Stopping the running WoW client and WarcraftXL host..."
|
Write-Host "Stopping the running WoW client..."
|
||||||
$runtimeProcesses | Stop-Process -Force
|
$runtimeProcesses | Stop-Process -Force
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
+1
Submodule vendor/modules/wxl-db2 added at b3b4e31cc4
+1
Submodule vendor/modules/wxl-grasswind added at b4a52b0e33
Vendored
+1
-1
Submodule vendor/modules/wxl-modern-adt updated: 0412b690c0...18221f6439
Vendored
-1
Submodule vendor/modules/wxl-modern-assets deleted from eb7c7c6646
+1
Submodule vendor/modules/wxl-modern-m2 added at ca841be8a9
Vendored
-1
Submodule vendor/modules/wxl-modern-render deleted from 3f246a5e20
+1
Submodule vendor/modules/wxl-modern-wmo added at e56fa7c93a
Vendored
+1
-1
Submodule vendor/modules/wxl-unit-outline updated: 29e5e29fa9...4e8123ec5d
+1
Submodule vendor/warcraftxl added at 4895cef6f4
@@ -1,69 +0,0 @@
|
|||||||
# Prerequisites
|
|
||||||
*.d
|
|
||||||
|
|
||||||
# Compiled Object files
|
|
||||||
*.slo
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Linker files
|
|
||||||
*.ilk
|
|
||||||
|
|
||||||
# Debugger Files
|
|
||||||
*.pdb
|
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
*.so.*
|
|
||||||
|
|
||||||
|
|
||||||
# Fortran module files
|
|
||||||
*.mod
|
|
||||||
*.smod
|
|
||||||
|
|
||||||
# Compiled Static libraries
|
|
||||||
*.lai
|
|
||||||
*.la
|
|
||||||
*.a
|
|
||||||
*.lib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
|
|
||||||
# Build directories
|
|
||||||
build/
|
|
||||||
Build/
|
|
||||||
build-*/
|
|
||||||
|
|
||||||
# CMake generated files
|
|
||||||
CMakeFiles/
|
|
||||||
CMakeCache.txt
|
|
||||||
cmake_install.cmake
|
|
||||||
Makefile
|
|
||||||
install_manifest.txt
|
|
||||||
compile_commands.json
|
|
||||||
|
|
||||||
# Temporary files
|
|
||||||
*.tmp
|
|
||||||
*.log
|
|
||||||
*.bak
|
|
||||||
*.swp
|
|
||||||
|
|
||||||
# vcpkg
|
|
||||||
vcpkg_installed/
|
|
||||||
|
|
||||||
# debug information files
|
|
||||||
*.dwo
|
|
||||||
|
|
||||||
# test output & cache
|
|
||||||
Testing/
|
|
||||||
.cache/
|
|
||||||
Vendored
-205
@@ -1,205 +0,0 @@
|
|||||||
# WarcraftXL. Two artifact families share this tree and cannot share one toolchain platform, so the file
|
|
||||||
# is platform-aware: configure -A Win32 for the injected DLL + patcher + proxy (32-bit), and -A x64 with
|
|
||||||
# -DWXL_BUILD_HOST=ON for the asset host (64-bit). build.ps1 drives both.
|
|
||||||
# Copyright (C) 2026 WarcraftXL. GPLv3 (see source headers).
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.20)
|
|
||||||
project(WarcraftXL LANGUAGES CXX)
|
|
||||||
|
|
||||||
# Static CRT everywhere: the DLLs load inside the player's Wow.exe and the host runs standalone on
|
|
||||||
# machines that have no reason to carry the toolset's brand-new VC++ redistributable. A dynamic CRT
|
|
||||||
# turns a missing/stale redist into a loader failure at process start (0xc0000142) with no log at all.
|
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
|
||||||
|
|
||||||
# The 64-bit asset host (WarcraftXLHost.exe) is opt-in: OFF by default so a contributor who only wants the
|
|
||||||
# DLL needs no x64 toolchain and pays no build/deploy cost. build.ps1 -Host flips it on in an x64 configure.
|
|
||||||
option(WXL_BUILD_HOST "Build WarcraftXLHost.exe (64-bit asset host)" OFF)
|
|
||||||
|
|
||||||
# wxl-modern-assets per-format toggles: exclude an entire format pipeline (source down-convert, both its
|
|
||||||
# DLL and host halves) at configure time, without touching source. common/ and textures/dds stay in
|
|
||||||
# unconditionally (shared infrastructure, not format-specific). ADT gets WXL_MODERN_ADT here once it
|
|
||||||
# migrates into wxl-modern-assets.
|
|
||||||
option(WXL_MODERN_M2 "Build wxl-modern-assets M2 support" ON)
|
|
||||||
option(WXL_MODERN_M3 "Build wxl-modern-assets M3 support" ON)
|
|
||||||
option(WXL_MODERN_WMO "Build wxl-modern-assets WMO support" ON)
|
|
||||||
option(WXL_MODERN_BLP "Build wxl-modern-assets BLP/texture support" ON)
|
|
||||||
|
|
||||||
set(WXL_MODERN_ASSETS_EXCLUDE_REGEX "")
|
|
||||||
if(NOT WXL_MODERN_M2)
|
|
||||||
string(APPEND WXL_MODERN_ASSETS_EXCLUDE_REGEX "|/wxl-modern-assets/(shared|host|src)/models/m2/")
|
|
||||||
endif()
|
|
||||||
if(NOT WXL_MODERN_M3)
|
|
||||||
string(APPEND WXL_MODERN_ASSETS_EXCLUDE_REGEX "|/wxl-modern-assets/(shared|host|src)/models/m3/")
|
|
||||||
endif()
|
|
||||||
if(NOT WXL_MODERN_WMO)
|
|
||||||
string(APPEND WXL_MODERN_ASSETS_EXCLUDE_REGEX "|/wxl-modern-assets/(shared|host|src)/models/wmo/")
|
|
||||||
endif()
|
|
||||||
if(NOT WXL_MODERN_BLP)
|
|
||||||
string(APPEND WXL_MODERN_ASSETS_EXCLUDE_REGEX "|/wxl-modern-assets/(shared|host|src)/textures/blp/")
|
|
||||||
endif()
|
|
||||||
string(REGEX REPLACE "^\\|" "" WXL_MODERN_ASSETS_EXCLUDE_REGEX "${WXL_MODERN_ASSETS_EXCLUDE_REGEX}")
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # feeds the IDE the real C++20 flags
|
|
||||||
|
|
||||||
set(WXL_DEFS WIN32_LEAN_AND_MEAN NOMINMAX _CRT_SECURE_NO_WARNINGS)
|
|
||||||
|
|
||||||
# Client directory to deploy the built artifacts into. Passed by build.ps1 (-DCLIENT_PATH=...) and cached.
|
|
||||||
set(CLIENT_PATH "" CACHE PATH "Client folder the built artifacts are copied into after each build")
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# 32-bit family (injected into the client): WarcraftXL.dll + wxl-patcher.exe + d3d9.dll
|
|
||||||
# =============================================================================
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
|
||||||
# --- Automatic, recursive source discovery (no hand-written paths) -----------------------------
|
|
||||||
# CONFIGURE_DEPENDS re-globs at build time, so dropping a file (or a whole script) needs no edit here.
|
|
||||||
# The DLL excludes the patcher/host/gpu trees; the host (64-bit) takes its own slice in the EQUAL 8 block.
|
|
||||||
file(GLOB_RECURSE WXL_CORE_SRC CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
|
|
||||||
list(FILTER WXL_CORE_SRC EXCLUDE REGEX "/src/(patcher|host|gpu)/")
|
|
||||||
|
|
||||||
# =========================================================================
|
|
||||||
# Target 1: WarcraftXL.dll (32-bit, injected) = SDK + runtime scripts
|
|
||||||
# runtime scripts live in scripts/*/src/*.cpp; the cross-target byte-transform a module shares with
|
|
||||||
# the host lives in scripts/*/shared/*.cpp. Both compile straight into the DLL (self-registering).
|
|
||||||
# =========================================================================
|
|
||||||
file(GLOB_RECURSE WXL_RUNTIME_SCRIPT CONFIGURE_DEPENDS
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/src/*.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/shared/*.cpp")
|
|
||||||
if(WXL_MODERN_ASSETS_EXCLUDE_REGEX)
|
|
||||||
list(FILTER WXL_RUNTIME_SCRIPT EXCLUDE REGEX "${WXL_MODERN_ASSETS_EXCLUDE_REGEX}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Vendored ImGui (core + dx9/win32 backends). Compiled in but DORMANT until a script wires it up.
|
|
||||||
file(GLOB WXL_IMGUI CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/deps/imgui/*.cpp")
|
|
||||||
|
|
||||||
# FlatBuffers runtime (flexbuffers string utils) for the host IPC client (runtime/storage).
|
|
||||||
set(WXL_FLATBUFFERS "${CMAKE_CURRENT_SOURCE_DIR}/deps/flatbuffers/src/util.cpp")
|
|
||||||
|
|
||||||
add_library(WarcraftXL SHARED ${WXL_CORE_SRC} ${WXL_RUNTIME_SCRIPT} ${WXL_IMGUI} ${WXL_FLATBUFFERS})
|
|
||||||
set_target_properties(WarcraftXL PROPERTIES OUTPUT_NAME "WarcraftXL" PREFIX "")
|
|
||||||
target_include_directories(WarcraftXL PRIVATE
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/minhook/include"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/imgui"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/flatbuffers/include")
|
|
||||||
|
|
||||||
add_subdirectory(deps/minhook)
|
|
||||||
target_link_libraries(WarcraftXL PRIVATE minhook d3d9 d3dcompiler shell32 delayimp)
|
|
||||||
# D3D12 and the shader compiler are feature-path dependencies (post-fx, grass capture, liquid
|
|
||||||
# shaders), not boot dependencies. Delay-loading keeps the DLL loadable on machines without them;
|
|
||||||
# every call site resolves or guards availability before touching those paths.
|
|
||||||
target_link_options(WarcraftXL PRIVATE "/DELAYLOAD:d3d12.dll" "/DELAYLOAD:d3dcompiler_47.dll")
|
|
||||||
target_compile_definitions(WarcraftXL PRIVATE ${WXL_DEFS})
|
|
||||||
|
|
||||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${WXL_CORE_SRC} ${WXL_RUNTIME_SCRIPT})
|
|
||||||
|
|
||||||
# Deploy: copy the freshly linked DLL into the client folder after every build.
|
|
||||||
if(CLIENT_PATH)
|
|
||||||
add_custom_command(TARGET WarcraftXL POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:WarcraftXL>" "${CLIENT_PATH}/WarcraftXL.dll"
|
|
||||||
COMMENT "Deploy WarcraftXL.dll -> ${CLIENT_PATH}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Per-module CMake hook: a module may ship scripts/<m>/module.cmake to extend the WarcraftXL target
|
|
||||||
# (add a vendored library, extra include dirs, link libraries). The file runs with the target defined
|
|
||||||
# and ${CMAKE_CURRENT_LIST_DIR} pointing at the module folder. Optional; most modules need none.
|
|
||||||
file(GLOB WXL_MODULE_CMAKES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/module.cmake")
|
|
||||||
foreach(_wxl_module ${WXL_MODULE_CMAKES})
|
|
||||||
include("${_wxl_module}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# =========================================================================
|
|
||||||
# Target 2: wxl-patcher.exe = the offline PE patcher + patcher scripts
|
|
||||||
# =========================================================================
|
|
||||||
file(GLOB WXL_PATCHER_CORE CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/patcher/*.cpp")
|
|
||||||
file(GLOB_RECURSE WXL_PATCHER_SCRIPT CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/patcher/*.cpp")
|
|
||||||
|
|
||||||
# src/common/ compiles into every binary (leveled logger, env config, shared helpers): the
|
|
||||||
# patcher and proxy do not link core, and the host is another architecture, so the shared
|
|
||||||
# infrastructure is object-level, not a link dependency.
|
|
||||||
file(GLOB WXL_COMMON_SRC CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/common/*.cpp")
|
|
||||||
|
|
||||||
add_executable(wxl-patcher ${WXL_PATCHER_CORE} ${WXL_PATCHER_SCRIPT} ${WXL_COMMON_SRC})
|
|
||||||
set_target_properties(wxl-patcher PROPERTIES OUTPUT_NAME "wxl-patcher")
|
|
||||||
target_include_directories(wxl-patcher PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
|
||||||
target_compile_definitions(wxl-patcher PRIVATE ${WXL_DEFS})
|
|
||||||
|
|
||||||
# =========================================================================
|
|
||||||
# Target 3: d3d9.dll = the D3D9On12 proxy
|
|
||||||
# =========================================================================
|
|
||||||
file(GLOB WXL_GPU_SRC CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/gpu/*.cpp")
|
|
||||||
|
|
||||||
add_library(d3d9 SHARED ${WXL_GPU_SRC} ${WXL_COMMON_SRC})
|
|
||||||
set_target_properties(d3d9 PROPERTIES OUTPUT_NAME "d3d9" PREFIX "")
|
|
||||||
target_include_directories(d3d9 PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
|
||||||
target_link_libraries(d3d9 PRIVATE d3d12 dxgi dcomp d3dcompiler delayimp)
|
|
||||||
# The proxy must load on every machine Wow.exe runs on -- it shadows a static import of the exe, so
|
|
||||||
# a hard dependency of the proxy is a hard dependency of the game (loader failure 0xc0000142 on
|
|
||||||
# machines without D3D12). All On12/D3D12 machinery is delay-loaded; EnsureDevice() checks that
|
|
||||||
# d3d12.dll is actually present before the first delay-loaded call, else the proxy runs as a pure
|
|
||||||
# native pass-through.
|
|
||||||
target_link_options(d3d9 PRIVATE "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/src/gpu/Proxy.def"
|
|
||||||
"/DELAYLOAD:d3d12.dll" "/DELAYLOAD:dxgi.dll" "/DELAYLOAD:dcomp.dll" "/DELAYLOAD:d3dcompiler_47.dll")
|
|
||||||
target_compile_definitions(d3d9 PRIVATE ${WXL_DEFS})
|
|
||||||
|
|
||||||
# Deploy: copy the freshly linked proxy into the client folder after every build.
|
|
||||||
if(CLIENT_PATH)
|
|
||||||
add_custom_command(TARGET d3d9 POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:d3d9>" "${CLIENT_PATH}/d3d9.dll"
|
|
||||||
COMMENT "Deploy d3d9.dll -> ${CLIENT_PATH}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# 64-bit family (opt-in): WarcraftXLHost.exe = archive owner + IPC transport.
|
|
||||||
# Format-blind: src/host/ + the modules' scripts/*/host/ handlers + their scripts/*/shared/ transforms.
|
|
||||||
# StormLib + FlatBuffers (deps/). Requires an x64 toolchain.
|
|
||||||
# =============================================================================
|
|
||||||
if(WXL_BUILD_HOST AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
# StormLib (vendored) supplies MPQ reading. Static, read-only use; no install/tests.
|
|
||||||
set(STORM_SKIP_INSTALL ON CACHE BOOL "" FORCE)
|
|
||||||
set(STORM_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
|
||||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
|
||||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/deps/stormlib" "${CMAKE_BINARY_DIR}/stormlib")
|
|
||||||
|
|
||||||
file(GLOB_RECURSE WXL_HOST_CORE CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/host/*.cpp")
|
|
||||||
file(GLOB_RECURSE WXL_HOST_SCRIPT CONFIGURE_DEPENDS
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/host/*.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/*/shared/*.cpp")
|
|
||||||
if(WXL_MODERN_ASSETS_EXCLUDE_REGEX)
|
|
||||||
list(FILTER WXL_HOST_SCRIPT EXCLUDE REGEX "${WXL_MODERN_ASSETS_EXCLUDE_REGEX}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# The shared infrastructure (leveled logger, env config) compiles straight into the host too.
|
|
||||||
file(GLOB WXL_COMMON_SRC CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/common/*.cpp")
|
|
||||||
|
|
||||||
add_executable(WarcraftXLHost
|
|
||||||
${WXL_HOST_CORE}
|
|
||||||
${WXL_HOST_SCRIPT}
|
|
||||||
${WXL_COMMON_SRC}
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/flatbuffers/src/util.cpp")
|
|
||||||
set_target_properties(WarcraftXLHost PROPERTIES OUTPUT_NAME "WarcraftXLHost")
|
|
||||||
target_include_directories(WarcraftXLHost PRIVATE
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/host"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/flatbuffers/include"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/stormlib/src")
|
|
||||||
target_link_libraries(WarcraftXLHost PRIVATE storm)
|
|
||||||
target_compile_definitions(WarcraftXLHost PRIVATE ${WXL_DEFS} WXL_HOST=1)
|
|
||||||
|
|
||||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${WXL_HOST_CORE} ${WXL_HOST_SCRIPT})
|
|
||||||
|
|
||||||
# Deploy the host into the client's Utils folder after build.
|
|
||||||
if(CLIENT_PATH)
|
|
||||||
add_custom_command(TARGET WarcraftXLHost POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${CLIENT_PATH}/Utils"
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:WarcraftXLHost>" "${CLIENT_PATH}/Utils/WarcraftXLHost.exe"
|
|
||||||
COMMENT "Deploy WarcraftXLHost.exe -> ${CLIENT_PATH}/Utils")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# A 64-bit configure that did not ask for the host builds nothing; nudge toward the right flags.
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WXL_BUILD_HOST)
|
|
||||||
message(WARNING "x64 configure without -DWXL_BUILD_HOST=ON builds nothing; the 32-bit family needs -A Win32.")
|
|
||||||
endif()
|
|
||||||
Vendored
-674
@@ -1,674 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
|
||||||
or can get the source code. And you must show them these terms so they
|
|
||||||
know their rights.
|
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
|
||||||
that there is no warranty for this free software. For both users' and
|
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
|
||||||
changed, so that their problems will not be attributed erroneously to
|
|
||||||
authors of previous versions.
|
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the special requirements of the GNU Affero General Public License,
|
|
||||||
section 13, concerning interaction through a network will apply to the
|
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
|
||||||
notice like this when it starts in an interactive mode:
|
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
||||||
Vendored
-674
@@ -1,674 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
|
||||||
or can get the source code. And you must show them these terms so they
|
|
||||||
know their rights.
|
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
|
||||||
that there is no warranty for this free software. For both users' and
|
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
|
||||||
changed, so that their problems will not be attributed erroneously to
|
|
||||||
authors of previous versions.
|
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the special requirements of the GNU Affero General Public License,
|
|
||||||
section 13, concerning interaction through a network will apply to the
|
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
|
||||||
notice like this when it starts in an interactive mode:
|
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
||||||
Vendored
-126
@@ -1,126 +0,0 @@
|
|||||||
# WarcraftXL
|
|
||||||
|
|
||||||
**A modding framework for the World of Warcraft 3.3.5a (build 12340) client.**
|
|
||||||
|
|
||||||
WarcraftXL loads into the running client and gives mods a clean, typed way to talk to the engine -
|
|
||||||
the same idea as RED4ext for Cyberpunk 2077 or SKSE for Skyrim. The framework owns the hard,
|
|
||||||
repetitive parts (getting into the process, the hook engine, client offsets, engine bindings, an
|
|
||||||
event bus, file-format contracts); your mods - here called **modules / scripts** - own the actual features.
|
|
||||||
|
|
||||||
> **Core principle.** If something is needed everywhere and always works the same way, it belongs in
|
|
||||||
> the core. Anything that is a *feature* - a decision, an effect, an editor - is a module. The core
|
|
||||||
> stays small and reusable; the modules stay free to do whatever they want.
|
|
||||||
|
|
||||||
## How it works
|
|
||||||
|
|
||||||
`WarcraftXL.dll` is the framework. It boots inside the client, brings up the hook engine, and raises
|
|
||||||
a set of events. Each module is a small self-contained unit under `scripts/` that subscribes to those
|
|
||||||
events and uses the core's bindings to read and drive the game. Drop a module in, rebuild, and it is
|
|
||||||
live - no separate injector, no patched data files.
|
|
||||||
|
|
||||||
The core is organised as four pillars, so a module never touches a raw address itself:
|
|
||||||
|
|
||||||
| Pillar | Namespace | What it gives a module |
|
|
||||||
|---|---|---|
|
|
||||||
| **Offsets** | `wxl::offsets` | The curated client addresses and struct layouts. Internal - modules never include these directly. |
|
|
||||||
| **Bindings** | `wxl::game` | Typed, zero-overhead calls into engine functions (`Native<Fn>(addr)(args...)`) plus an enumerable catalog of `{name, address, signature}`. |
|
|
||||||
| **Events** | `wxl::events` | A POD-dispatch event bus. A module subclasses `EventScript` and binds member functions with `on<&Self::OnEndScene>(Event::OnEndScene)`. |
|
|
||||||
| **Assets** | `wxl::asset` | In-memory contracts for the client's file formats (ADT, WMO, M2, WDT, WDL) so modules read structured data, not byte soup. |
|
|
||||||
|
|
||||||
A module looks like this - bind in the constructor, react in the handler:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
class MyModule final : public wxl::events::EventScript {
|
|
||||||
public:
|
|
||||||
MyModule() { on<&MyModule::OnEndScene>(wxl::events::Event::OnEndScene); }
|
|
||||||
void OnEndScene(const wxl::events::EndSceneArgs& a) { /* draw, read world, edit... */ }
|
|
||||||
};
|
|
||||||
MyModule g_myModule; // file-scope instance self-registers at load
|
|
||||||
```
|
|
||||||
|
|
||||||
## Layout
|
|
||||||
|
|
||||||
```
|
|
||||||
src/
|
|
||||||
├── core/ Hook · Logger · Mem · Main process bring-up, hook engine, entry point
|
|
||||||
├── offsets/ engine/ · game/ client addresses + struct layouts (internal)
|
|
||||||
├── game/ camera · doodad · world · ui typed engine bindings (the wxl::game pillar)
|
|
||||||
│ m2 · wmo · adt · unit · gx ·
|
|
||||||
│ io · mem ...
|
|
||||||
├── events/ Event · EventScript the event bus + the module base class
|
|
||||||
├── asset/ adt · wmo · m2 · wdt · wdl file-format contracts
|
|
||||||
├── services/ asset higher-level services over the pillars
|
|
||||||
└── runtime/ RenderHooks per-frame / device hooks the events ride on
|
|
||||||
|
|
||||||
scripts/ the modules (each builds into WarcraftXL.dll)
|
|
||||||
├── wxl-mini-noggit an in-client map editor (ImGui + 3D gizmo): pick a doodad, move/rotate/scale it
|
|
||||||
├── wxl-unit-outline a unit outline / highlight effect
|
|
||||||
└── wxl-glue-unlock glue-screen unlock
|
|
||||||
|
|
||||||
deps/ vendored: MinHook, Dear ImGui + ImGuizmo, StormLib, FlatBuffers
|
|
||||||
```
|
|
||||||
|
|
||||||
Every address the bindings rely on lives in `src/offsets/`, named and annotated. The reasoning behind
|
|
||||||
each one is kept in the project's RE documentation - the code follows it.
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
The target client is a 32-bit process, so everything builds **Win32**.
|
|
||||||
|
|
||||||
**Requirements**
|
|
||||||
- CMake ≥ 3.25
|
|
||||||
- A Win32 C++17 toolchain (Visual Studio 2022 recommended)
|
|
||||||
- A legally-obtained 3.3.5a (12340) client
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cmake -B build
|
|
||||||
cmake --build build --config Release --target WarcraftXL
|
|
||||||
```
|
|
||||||
|
|
||||||
Output: `WarcraftXL.dll`. Vendored dependencies build with the project.
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
1. Place `WarcraftXL.dll` next to `Wow.exe` and load it into the client (import-table entry / loader).
|
|
||||||
2. Launch. The framework writes a startup log on bootstrap - check it to confirm modules came up.
|
|
||||||
|
|
||||||
Each client process launches its own `WarcraftXLHost.exe` session (IPC named objects are scoped by
|
|
||||||
the Wow.exe PID), so multiple concurrent clients do not share a mailbox.
|
|
||||||
|
|
||||||
> Modifying a client binary is on you: work on a **copy**, keep an untouched backup, and only point
|
|
||||||
> this at a client and server you are permitted to modify and connect to.
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
Thanks to everyone who has helped shape WarcraftXL, with code, reverse-engineering, ideas, or feedback:
|
|
||||||
|
|
||||||
- [Furioz](https://github.com/Furioz420)
|
|
||||||
- [Tester](https://github.com/TesterWoWDev)
|
|
||||||
- [Duskhaven](https://git.duskhaven.net/Duskhaven)
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
**WarcraftXL is free, and it always will be - forever.** Nothing here is gated, and nothing ever
|
|
||||||
will be. Sponsoring is completely optional - just a way to support the project and the time behind
|
|
||||||
it, if you want to and can.
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://github.com/sponsors/iThorgrim"><img src="https://raw.githubusercontent.com/iThorgrim/ithorgrim/refs/heads/main/assets/sponsor.svg" alt="Sponsor iThorgrim" height="48"></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## Legal
|
|
||||||
|
|
||||||
WarcraftXL is an **interoperability project**. It distributes no Blizzard code and no game assets, and
|
|
||||||
runs only against a client you supply and own, reading that client's own files at runtime.
|
|
||||||
Reverse-engineering is limited to what is necessary for interoperability.
|
|
||||||
|
|
||||||
World of Warcraft and Wrath of the Lich King are trademarks of Blizzard Entertainment. This project is
|
|
||||||
not affiliated with or endorsed by Blizzard.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Released under the **GNU General Public License v3.0** - see [LICENSE](LICENSE).
|
|
||||||
|
|
||||||
Bundles [MinHook](https://github.com/TsudaKageyu/minhook) (© Tsuda Kageyu, BSD 2-Clause),
|
|
||||||
[Dear ImGui](https://github.com/ocornut/imgui) + [ImGuizmo](https://github.com/CedricGuillemet/ImGuizmo),
|
|
||||||
and [StormLib](https://github.com/ladislav-zezula/StormLib) under `deps/`, with their licenses retained.
|
|
||||||
Vendored
-135
@@ -1,135 +0,0 @@
|
|||||||
#requires -Version 5.1
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Build + deploy WarcraftXL: WarcraftXL.dll (injected), d3d9.dll (proxy) and wxl-patcher.exe (32-bit).
|
|
||||||
|
|
||||||
.PARAMETER Config
|
|
||||||
Build configuration. Default: Release.
|
|
||||||
|
|
||||||
.PARAMETER ClientPath
|
|
||||||
Client directory to deploy into. Optional once it has been cached by a first run.
|
|
||||||
|
|
||||||
.PARAMETER Clean
|
|
||||||
Delete the build directory before configuring (forces a from-scratch build).
|
|
||||||
|
|
||||||
.PARAMETER AutoPatch
|
|
||||||
After the build, run wxl-patcher on the client's Wow.exe. The patcher is idempotent
|
|
||||||
(it skips an already-patched exe and backs the original up to Wow.exe.orig on first run).
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
.\build.ps1
|
|
||||||
.EXAMPLE
|
|
||||||
.\build.ps1 -ClientPath "D:\Path\To\Client" -Clean
|
|
||||||
.EXAMPLE
|
|
||||||
.\build.ps1 -AutoPatch
|
|
||||||
#>
|
|
||||||
param(
|
|
||||||
[string]$Config = "Release",
|
|
||||||
[string]$ClientPath,
|
|
||||||
[switch]$Clean,
|
|
||||||
[switch]$AutoPatch = true,
|
|
||||||
[switch]$BuildHost
|
|
||||||
)
|
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
|
||||||
|
|
||||||
$root = $PSScriptRoot
|
|
||||||
$buildDir = Join-Path $root "build\dll"
|
|
||||||
$buildHostDir = Join-Path $root "build\host"
|
|
||||||
|
|
||||||
if (-not (Test-Path (Join-Path $root "CMakeLists.txt"))) {
|
|
||||||
throw "CMakeLists.txt is missing from '$root'. Place build.ps1 in the project root directory (next to CMakeLists.txt)."
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-CachedClientPath([string]$cacheDir) {
|
|
||||||
$cache = Join-Path $cacheDir "CMakeCache.txt"
|
|
||||||
if (Test-Path $cache) {
|
|
||||||
$hit = Select-String -Path $cache -Pattern '^CLIENT_PATH:PATH=(.+)$' | Select-Object -First 1
|
|
||||||
if ($hit) { return $hit.Matches[0].Groups[1].Value.Trim() }
|
|
||||||
}
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-not $ClientPath) {
|
|
||||||
$ClientPath = Get-CachedClientPath $buildDir
|
|
||||||
}
|
|
||||||
if (-not $ClientPath) {
|
|
||||||
throw "No client path is known. Run the command once with -ClientPath '<client folder>' (it will be stored in the CMake cache)."
|
|
||||||
}
|
|
||||||
if (-not (Test-Path $ClientPath)) {
|
|
||||||
throw "Client path not found: $ClientPath"
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Project : $root"
|
|
||||||
Write-Host "Client : $ClientPath"
|
|
||||||
Write-Host "Config : $Config"
|
|
||||||
Write-Host ""
|
|
||||||
|
|
||||||
function Invoke-Native([string]$exe, [string[]]$cmdArgs) {
|
|
||||||
Write-Host ">> $exe $($cmdArgs -join ' ')" -ForegroundColor Cyan
|
|
||||||
$prev = $ErrorActionPreference
|
|
||||||
$ErrorActionPreference = "Continue"
|
|
||||||
try { & $exe @cmdArgs } finally { $ErrorActionPreference = $prev }
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "Failure ($LASTEXITCODE): $exe $($cmdArgs -join ' ')" }
|
|
||||||
}
|
|
||||||
|
|
||||||
function Build-Dll {
|
|
||||||
Write-Host "=== WarcraftXL.dll (32-bit) ===" -ForegroundColor Green
|
|
||||||
|
|
||||||
if ($Clean -and (Test-Path $buildDir)) {
|
|
||||||
Write-Host "Clean $buildDir" -ForegroundColor Yellow
|
|
||||||
Remove-Item -Recurse -Force $buildDir
|
|
||||||
}
|
|
||||||
|
|
||||||
$needConfigure = $Clean `
|
|
||||||
-or $PSBoundParameters.ContainsKey('ClientPath') `
|
|
||||||
-or (-not (Test-Path (Join-Path $buildDir "CMakeCache.txt")))
|
|
||||||
if ($needConfigure) {
|
|
||||||
Invoke-Native "cmake" @("-S", $root, "-B", $buildDir, "-A", "Win32", "-DCLIENT_PATH=$ClientPath")
|
|
||||||
}
|
|
||||||
|
|
||||||
Invoke-Native "cmake" @("--build", $buildDir, "--config", $Config, "--parallel")
|
|
||||||
Write-Host ""
|
|
||||||
}
|
|
||||||
|
|
||||||
function Build-Host {
|
|
||||||
Write-Host "=== WarcraftXLHost.exe (64-bit) ===" -ForegroundColor Green
|
|
||||||
|
|
||||||
if ($Clean -and (Test-Path $buildHostDir)) {
|
|
||||||
Write-Host "Clean $buildHostDir" -ForegroundColor Yellow
|
|
||||||
Remove-Item -Recurse -Force $buildHostDir
|
|
||||||
}
|
|
||||||
|
|
||||||
$needConfigure = $Clean `
|
|
||||||
-or $PSBoundParameters.ContainsKey('ClientPath') `
|
|
||||||
-or (-not (Test-Path (Join-Path $buildHostDir "CMakeCache.txt")))
|
|
||||||
if ($needConfigure) {
|
|
||||||
Invoke-Native "cmake" @("-S", $root, "-B", $buildHostDir, "-A", "x64", "-DWXL_BUILD_HOST=ON", "-DCLIENT_PATH=$ClientPath")
|
|
||||||
}
|
|
||||||
|
|
||||||
Invoke-Native "cmake" @("--build", $buildHostDir, "--config", $Config, "--parallel")
|
|
||||||
Write-Host ""
|
|
||||||
}
|
|
||||||
|
|
||||||
function Invoke-AutoPatch {
|
|
||||||
$patcher = Join-Path $buildDir "$Config\wxl-patcher.exe"
|
|
||||||
if (-not (Test-Path $patcher)) { $patcher = Join-Path $ClientPath "wxl-patcher.exe" }
|
|
||||||
if (-not (Test-Path $patcher)) {
|
|
||||||
throw "wxl-patcher.exe not found. Build first (.\build.ps1)."
|
|
||||||
}
|
|
||||||
$wow = Join-Path $ClientPath "Wow.exe"
|
|
||||||
if (-not (Test-Path $wow)) { throw "Wow.exe not found: $wow" }
|
|
||||||
|
|
||||||
Write-Host "=== AutoPatch ===" -ForegroundColor Green
|
|
||||||
Invoke-Native $patcher @($wow)
|
|
||||||
Write-Host ""
|
|
||||||
}
|
|
||||||
|
|
||||||
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
|
||||||
|
|
||||||
Build-Dll
|
|
||||||
if ($BuildHost) { Build-Host }
|
|
||||||
if ($AutoPatch) { Invoke-AutoPatch }
|
|
||||||
|
|
||||||
$sw.Stop()
|
|
||||||
Write-Host "OK - build + deploy in $([int]$sw.Elapsed.TotalSeconds)s -> $ClientPath" -ForegroundColor Green
|
|
||||||
Vendored
-9
@@ -1,9 +0,0 @@
|
|||||||
Vendored third-party dependencies (self-contained).
|
|
||||||
|
|
||||||
Contents:
|
|
||||||
stormlib/ - MPQ archive access. Used by: host (MpqStore). Built via add_subdirectory.
|
|
||||||
flatbuffers/ - FlexBuffers payloads for the IPC contract. Used by: host + DLL (ipc/).
|
|
||||||
Header-only for our use plus src/util.cpp compiled into the host.
|
|
||||||
minhook/ - inline detour engine. Used by: DLL only (core/Hook). Wired with the DLL target.
|
|
||||||
|
|
||||||
These are the only external dependencies.
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
buildifier: latest
|
|
||||||
matrix:
|
|
||||||
bazel:
|
|
||||||
- 7.x
|
|
||||||
- 8.x
|
|
||||||
tasks:
|
|
||||||
verify_ubuntu2004:
|
|
||||||
platform: ubuntu2004
|
|
||||||
bazel: ${{ bazel }}
|
|
||||||
environment:
|
|
||||||
CC: clang
|
|
||||||
SWIFT_VERSION: "5.10"
|
|
||||||
SWIFT_HOME: "$HOME/swift-$SWIFT_VERSION"
|
|
||||||
PATH: "$PATH:$SWIFT_HOME/usr/bin"
|
|
||||||
shell_commands:
|
|
||||||
- "echo --- Downloading and extracting Swift $SWIFT_VERSION to $SWIFT_HOME"
|
|
||||||
- "mkdir $SWIFT_HOME"
|
|
||||||
- "curl https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu2004/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu20.04.tar.gz | tar xvz --strip-components=1 -C $SWIFT_HOME"
|
|
||||||
build_targets:
|
|
||||||
- "//..."
|
|
||||||
test_targets:
|
|
||||||
- "//..."
|
|
||||||
verify_ubuntu2204:
|
|
||||||
platform: ubuntu2204
|
|
||||||
bazel: ${{ bazel }}
|
|
||||||
environment:
|
|
||||||
CC: clang
|
|
||||||
SWIFT_VERSION: "5.10"
|
|
||||||
SWIFT_HOME: "$HOME/swift-$SWIFT_VERSION"
|
|
||||||
PATH: "$PATH:$SWIFT_HOME/usr/bin"
|
|
||||||
shell_commands:
|
|
||||||
- "echo --- Downloading and extracting Swift $SWIFT_VERSION to $SWIFT_HOME"
|
|
||||||
- "mkdir $SWIFT_HOME"
|
|
||||||
- "curl https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu2204/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu22.04.tar.gz | tar xvz --strip-components=1 -C $SWIFT_HOME"
|
|
||||||
build_targets:
|
|
||||||
- "//..."
|
|
||||||
test_targets:
|
|
||||||
- "//..."
|
|
||||||
test_module_cpp:
|
|
||||||
platform: ubuntu2204
|
|
||||||
bazel: ${{ bazel }}
|
|
||||||
working_directory: tests/bazel_repository_test_dir
|
|
||||||
build_targets:
|
|
||||||
- "//..."
|
|
||||||
test_module_ts:
|
|
||||||
platform: ubuntu2204
|
|
||||||
bazel: ${{ bazel }}
|
|
||||||
working_directory: tests/ts/bazel_repository_test_dir
|
|
||||||
test_targets:
|
|
||||||
- "//..."
|
|
||||||
verify_macos:
|
|
||||||
platform: macos
|
|
||||||
bazel: ${{ bazel }}
|
|
||||||
xcode_version: "15.2"
|
|
||||||
build_targets:
|
|
||||||
- "//:flatbuffers"
|
|
||||||
- "//:flatc"
|
|
||||||
test_targets:
|
|
||||||
- "//tests:flatbuffers_test"
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
ts/node_modules
|
|
||||||
|
|
||||||
# Test workspaces
|
|
||||||
tests/bazel_repository_test_dir
|
|
||||||
tests/ts/bazel_repository_test_dir
|
|
||||||
-18
@@ -1,18 +0,0 @@
|
|||||||
# We cannot use "common" here because the "version" command doesn't support
|
|
||||||
# --deleted_packages. We need to specify it for both build and query instead.
|
|
||||||
build --deleted_packages=tests/bazel_repository_test_dir,tests/ts/bazel_repository_test_dir
|
|
||||||
query --deleted_packages=tests/bazel_repository_test_dir,tests/ts/bazel_repository_test_dir
|
|
||||||
# Point tools such as coursier (used in rules_jvm_external) to Bazel's internal JDK
|
|
||||||
# suggested in https://github.com/bazelbuild/rules_jvm_external/issues/445
|
|
||||||
common --repo_env=JAVA_HOME=../bazel_tools/jdk
|
|
||||||
common --action_env=JAVA_HOME=../bazel_tools/jdk
|
|
||||||
# Workaround "Error: need --enable_runfiles on Windows for to support rules_js"
|
|
||||||
common:windows --enable_runfiles
|
|
||||||
# Swift is not required on Windows
|
|
||||||
common:windows --deleted_packages=swift
|
|
||||||
# Ignore warnings in external dependencies
|
|
||||||
build --per_file_copt=external/.*@-Wno-everything --host_per_file_copt=external/.*@-Wno-everything
|
|
||||||
# Honor the setting of `skipLibCheck` in the tsconfig.json file.
|
|
||||||
common --@aspect_rules_ts//ts:skipLibCheck=honor_tsconfig
|
|
||||||
# Use "tsc" as the transpiler when ts_project has no `transpiler` set.
|
|
||||||
common --@aspect_rules_ts//ts:default_to_tsc_transpiler
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
Language: Cpp
|
|
||||||
BasedOnStyle: Google
|
|
||||||
...
|
|
||||||
|
|
||||||
-347
@@ -1,347 +0,0 @@
|
|||||||
---
|
|
||||||
FormatStyle: "file"
|
|
||||||
WarningsAsErrors: "*"
|
|
||||||
HeaderFilterRegex: ".*"
|
|
||||||
Checks: "google-build-explicit-make-pair,
|
|
||||||
google-build-namespaces,
|
|
||||||
google-build-using-namespace,
|
|
||||||
google-default-arguments,
|
|
||||||
google-explicit-constructor,
|
|
||||||
google-global-names-in-headers,
|
|
||||||
google-objc-avoid-nsobject-new,
|
|
||||||
google-objc-avoid-throwing-exception,
|
|
||||||
google-objc-function-naming,
|
|
||||||
google-objc-global-variable-declaration,
|
|
||||||
google-readability-avoid-underscore-in-googletest-name,
|
|
||||||
google-readability-braces-around-statements,
|
|
||||||
google-readability-casting,
|
|
||||||
google-readability-function-size,
|
|
||||||
google-readability-namespace-comments,
|
|
||||||
google-runtime-int,
|
|
||||||
google-runtime-operator,
|
|
||||||
google-upgrade-googletest-case,
|
|
||||||
clang-analyzer-apiModeling.StdCLibraryFunctions,
|
|
||||||
clang-analyzer-apiModeling.TrustNonnull,
|
|
||||||
clang-analyzer-apiModeling.google.GTest,
|
|
||||||
clang-analyzer-apiModeling.llvm.CastValue,
|
|
||||||
clang-analyzer-apiModeling.llvm.ReturnValue,
|
|
||||||
clang-analyzer-core.CallAndMessage,
|
|
||||||
clang-analyzer-core.CallAndMessageModeling,
|
|
||||||
clang-analyzer-core.DivideZero,
|
|
||||||
clang-analyzer-core.DynamicTypePropagation,
|
|
||||||
clang-analyzer-core.NonNullParamChecker,
|
|
||||||
clang-analyzer-core.NonnilStringConstants,
|
|
||||||
clang-analyzer-core.NullDereference,
|
|
||||||
clang-analyzer-core.StackAddrEscapeBase,
|
|
||||||
clang-analyzer-core.StackAddressEscape,
|
|
||||||
clang-analyzer-core.UndefinedBinaryOperatorResult,
|
|
||||||
clang-analyzer-core.VLASize,
|
|
||||||
clang-analyzer-core.builtin.BuiltinFunctions,
|
|
||||||
clang-analyzer-core.builtin.NoReturnFunctions,
|
|
||||||
clang-analyzer-core.uninitialized.ArraySubscript,
|
|
||||||
clang-analyzer-core.uninitialized.Assign,
|
|
||||||
clang-analyzer-core.uninitialized.Branch,
|
|
||||||
clang-analyzer-core.uninitialized.CapturedBlockVariable,
|
|
||||||
clang-analyzer-core.uninitialized.UndefReturn,
|
|
||||||
clang-analyzer-cplusplus.InnerPointer,
|
|
||||||
clang-analyzer-cplusplus.Move,
|
|
||||||
clang-analyzer-cplusplus.NewDelete,
|
|
||||||
clang-analyzer-cplusplus.NewDeleteLeaks,
|
|
||||||
clang-analyzer-cplusplus.PlacementNew,
|
|
||||||
clang-analyzer-cplusplus.PureVirtualCall,
|
|
||||||
clang-analyzer-cplusplus.SelfAssignment,
|
|
||||||
clang-analyzer-cplusplus.SmartPtrModeling,
|
|
||||||
clang-analyzer-cplusplus.StringChecker,
|
|
||||||
clang-analyzer-cplusplus.VirtualCallModeling,
|
|
||||||
clang-analyzer-deadcode.DeadStores,
|
|
||||||
clang-analyzer-fuchsia.HandleChecker,
|
|
||||||
clang-analyzer-nullability.NullPassedToNonnull,
|
|
||||||
clang-analyzer-nullability.NullReturnedFromNonnull,
|
|
||||||
clang-analyzer-nullability.NullabilityBase,
|
|
||||||
clang-analyzer-nullability.NullableDereferenced,
|
|
||||||
clang-analyzer-nullability.NullablePassedToNonnull,
|
|
||||||
clang-analyzer-nullability.NullableReturnedFromNonnull,
|
|
||||||
clang-analyzer-optin.cplusplus.UninitializedObject,
|
|
||||||
clang-analyzer-optin.cplusplus.VirtualCall,
|
|
||||||
clang-analyzer-optin.mpi.MPI-Checker,
|
|
||||||
clang-analyzer-optin.osx.OSObjectCStyleCast,
|
|
||||||
clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker,
|
|
||||||
clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker,
|
|
||||||
clang-analyzer-optin.performance.GCDAntipattern,
|
|
||||||
clang-analyzer-optin.performance.Padding,
|
|
||||||
clang-analyzer-optin.portability.UnixAPI,
|
|
||||||
clang-analyzer-osx.API,
|
|
||||||
clang-analyzer-osx.MIG,
|
|
||||||
clang-analyzer-osx.NSOrCFErrorDerefChecker,
|
|
||||||
clang-analyzer-osx.NumberObjectConversion,
|
|
||||||
clang-analyzer-osx.OSObjectRetainCount,
|
|
||||||
clang-analyzer-osx.ObjCProperty,
|
|
||||||
clang-analyzer-osx.SecKeychainAPI,
|
|
||||||
clang-analyzer-osx.cocoa.AtSync,
|
|
||||||
clang-analyzer-osx.cocoa.AutoreleaseWrite,
|
|
||||||
clang-analyzer-osx.cocoa.ClassRelease,
|
|
||||||
clang-analyzer-osx.cocoa.Dealloc,
|
|
||||||
clang-analyzer-osx.cocoa.IncompatibleMethodTypes,
|
|
||||||
clang-analyzer-osx.cocoa.Loops,
|
|
||||||
clang-analyzer-osx.cocoa.MissingSuperCall,
|
|
||||||
clang-analyzer-osx.cocoa.NSAutoreleasePool,
|
|
||||||
clang-analyzer-osx.cocoa.NSError,
|
|
||||||
clang-analyzer-osx.cocoa.NilArg,
|
|
||||||
clang-analyzer-osx.cocoa.NonNilReturnValue,
|
|
||||||
clang-analyzer-osx.cocoa.ObjCGenerics,
|
|
||||||
clang-analyzer-osx.cocoa.RetainCount,
|
|
||||||
clang-analyzer-osx.cocoa.RetainCountBase,
|
|
||||||
clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak,
|
|
||||||
clang-analyzer-osx.cocoa.SelfInit,
|
|
||||||
clang-analyzer-osx.cocoa.SuperDealloc,
|
|
||||||
clang-analyzer-osx.cocoa.UnusedIvars,
|
|
||||||
clang-analyzer-osx.cocoa.VariadicMethodTypes,
|
|
||||||
clang-analyzer-osx.coreFoundation.CFError,
|
|
||||||
clang-analyzer-osx.coreFoundation.CFNumber,
|
|
||||||
clang-analyzer-osx.coreFoundation.CFRetainRelease,
|
|
||||||
clang-analyzer-osx.coreFoundation.containers.OutOfBounds,
|
|
||||||
clang-analyzer-osx.coreFoundation.containers.PointerSizedValues,
|
|
||||||
clang-analyzer-security.FloatLoopCounter,
|
|
||||||
clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
|
|
||||||
clang-analyzer-security.insecureAPI.SecuritySyntaxChecker,
|
|
||||||
clang-analyzer-security.insecureAPI.UncheckedReturn,
|
|
||||||
clang-analyzer-security.insecureAPI.bcmp,
|
|
||||||
clang-analyzer-security.insecureAPI.bcopy,
|
|
||||||
clang-analyzer-security.insecureAPI.bzero,
|
|
||||||
clang-analyzer-security.insecureAPI.decodeValueOfObjCType,
|
|
||||||
clang-analyzer-security.insecureAPI.getpw,
|
|
||||||
clang-analyzer-security.insecureAPI.gets,
|
|
||||||
clang-analyzer-security.insecureAPI.mkstemp,
|
|
||||||
clang-analyzer-security.insecureAPI.mktemp,
|
|
||||||
clang-analyzer-security.insecureAPI.rand,
|
|
||||||
clang-analyzer-security.insecureAPI.strcpy,
|
|
||||||
clang-analyzer-security.insecureAPI.vfork,
|
|
||||||
clang-analyzer-unix.API,
|
|
||||||
clang-analyzer-unix.DynamicMemoryModeling,
|
|
||||||
clang-analyzer-unix.Malloc,
|
|
||||||
clang-analyzer-unix.MallocSizeof,
|
|
||||||
clang-analyzer-unix.MismatchedDeallocator,
|
|
||||||
clang-analyzer-unix.Vfork,
|
|
||||||
clang-analyzer-unix.cstring.BadSizeArg,
|
|
||||||
clang-analyzer-unix.cstring.CStringModeling,
|
|
||||||
clang-analyzer-unix.cstring.NullArg,
|
|
||||||
clang-analyzer-valist.CopyToSelf,
|
|
||||||
clang-analyzer-valist.Uninitialized,
|
|
||||||
clang-analyzer-valist.Unterminated,
|
|
||||||
clang-analyzer-valist.ValistBase,
|
|
||||||
clang-analyzer-webkit.NoUncountedMemberChecker,
|
|
||||||
clang-analyzer-webkit.RefCntblBaseVirtualDtor,
|
|
||||||
clang-analyzer-webkit.UncountedLambdaCapturesChecker,
|
|
||||||
|
|
||||||
################################################ Optional checks ################################################
|
|
||||||
|
|
||||||
#google-readability-todo,
|
|
||||||
#bugprone-argument-comment,
|
|
||||||
#bugprone-assert-side-effect,
|
|
||||||
#bugprone-bad-signal-to-kill-thread,
|
|
||||||
#bugprone-bool-pointer-implicit-conversion,
|
|
||||||
#bugprone-branch-clone,
|
|
||||||
#bugprone-copy-constructor-init,
|
|
||||||
#bugprone-dangling-handle,
|
|
||||||
#bugprone-dynamic-static-initializers,
|
|
||||||
#bugprone-easily-swappable-parameters,
|
|
||||||
#bugprone-exception-escape,
|
|
||||||
#bugprone-fold-init-type,
|
|
||||||
#bugprone-forward-declaration-namespace,
|
|
||||||
#bugprone-forwarding-reference-overload,
|
|
||||||
#bugprone-implicit-widening-of-multiplication-result,
|
|
||||||
#bugprone-inaccurate-erase,
|
|
||||||
#bugprone-incorrect-roundings,
|
|
||||||
#bugprone-infinite-loop,
|
|
||||||
#bugprone-integer-division,
|
|
||||||
#bugprone-lambda-function-name,
|
|
||||||
#bugprone-macro-parentheses,
|
|
||||||
#bugprone-macro-repeated-side-effects,
|
|
||||||
#bugprone-misplaced-operator-in-strlen-in-alloc,
|
|
||||||
#bugprone-misplaced-pointer-arithmetic-in-alloc,
|
|
||||||
#bugprone-misplaced-widening-cast,
|
|
||||||
#bugprone-move-forwarding-reference,
|
|
||||||
#bugprone-multiple-statement-macro,
|
|
||||||
#bugprone-narrowing-conversions,
|
|
||||||
#bugprone-no-escape,
|
|
||||||
#bugprone-not-null-terminated-result,
|
|
||||||
#bugprone-parent-virtual-call,
|
|
||||||
#bugprone-posix-return,
|
|
||||||
#bugprone-redundant-branch-condition,
|
|
||||||
#bugprone-reserved-identifier,
|
|
||||||
#bugprone-signal-handler,
|
|
||||||
#bugprone-signed-char-misuse,
|
|
||||||
#bugprone-sizeof-container,
|
|
||||||
#bugprone-sizeof-expression,
|
|
||||||
#bugprone-spuriously-wake-up-functions,
|
|
||||||
#bugprone-string-constructor,
|
|
||||||
#bugprone-string-integer-assignment,
|
|
||||||
#bugprone-string-literal-with-embedded-nul,
|
|
||||||
#bugprone-stringview-nullptr,
|
|
||||||
#bugprone-suspicious-enum-usage,
|
|
||||||
#bugprone-suspicious-include,
|
|
||||||
#bugprone-suspicious-memory-comparison,
|
|
||||||
#bugprone-suspicious-memset-usage,
|
|
||||||
#bugprone-suspicious-missing-comma,
|
|
||||||
#bugprone-suspicious-semicolon,
|
|
||||||
#bugprone-suspicious-string-compare,
|
|
||||||
#bugprone-swapped-arguments,
|
|
||||||
#bugprone-terminating-continue,
|
|
||||||
#bugprone-throw-keyword-missing,
|
|
||||||
#bugprone-too-small-loop-variable,
|
|
||||||
#bugprone-undefined-memory-manipulation,
|
|
||||||
#bugprone-undelegated-constructor,
|
|
||||||
#bugprone-unhandled-exception-at-new,
|
|
||||||
#bugprone-unhandled-self-assignment,
|
|
||||||
#bugprone-unused-raii,
|
|
||||||
#bugprone-unused-return-value,
|
|
||||||
#bugprone-use-after-move,
|
|
||||||
#bugprone-virtual-near-miss,
|
|
||||||
#cppcoreguidelines-avoid-c-arrays,
|
|
||||||
#cppcoreguidelines-avoid-goto,
|
|
||||||
#cppcoreguidelines-avoid-magic-numbers,
|
|
||||||
#cppcoreguidelines-avoid-non-const-global-variables,
|
|
||||||
#cppcoreguidelines-c-copy-assignment-signature,
|
|
||||||
#cppcoreguidelines-explicit-virtual-functions,
|
|
||||||
#cppcoreguidelines-init-variables,
|
|
||||||
#cppcoreguidelines-interfaces-global-init,
|
|
||||||
#cppcoreguidelines-macro-usage,
|
|
||||||
#cppcoreguidelines-narrowing-conversions,
|
|
||||||
#cppcoreguidelines-no-malloc,
|
|
||||||
#cppcoreguidelines-non-private-member-variables-in-classes,
|
|
||||||
#cppcoreguidelines-owning-memory,
|
|
||||||
#cppcoreguidelines-prefer-member-initializer,
|
|
||||||
#cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
|
||||||
#cppcoreguidelines-pro-bounds-constant-array-index,
|
|
||||||
#cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
|
||||||
#cppcoreguidelines-pro-type-const-cast,
|
|
||||||
#cppcoreguidelines-pro-type-cstyle-cast,
|
|
||||||
#cppcoreguidelines-pro-type-member-init,
|
|
||||||
#cppcoreguidelines-pro-type-reinterpret-cast,
|
|
||||||
#cppcoreguidelines-pro-type-static-cast-downcast,
|
|
||||||
#cppcoreguidelines-pro-type-union-access,
|
|
||||||
#cppcoreguidelines-pro-type-vararg,
|
|
||||||
#cppcoreguidelines-slicing,
|
|
||||||
#cppcoreguidelines-special-member-functions,
|
|
||||||
#cppcoreguidelines-virtual-class-destructor,
|
|
||||||
#hicpp-avoid-c-arrays,
|
|
||||||
#hicpp-avoid-goto,
|
|
||||||
#hicpp-braces-around-statements,
|
|
||||||
#hicpp-deprecated-headers,
|
|
||||||
#hicpp-exception-baseclass,
|
|
||||||
#hicpp-explicit-conversions,
|
|
||||||
#hicpp-function-size,
|
|
||||||
#hicpp-invalid-access-moved,
|
|
||||||
#hicpp-member-init,
|
|
||||||
#hicpp-move-const-arg,
|
|
||||||
#hicpp-multiway-paths-covered,
|
|
||||||
#hicpp-named-parameter,
|
|
||||||
#hicpp-new-delete-operators,
|
|
||||||
#hicpp-no-array-decay,
|
|
||||||
#hicpp-no-assembler,
|
|
||||||
#hicpp-no-malloc,
|
|
||||||
#hicpp-noexcept-move,
|
|
||||||
#hicpp-signed-bitwise,
|
|
||||||
#hicpp-special-member-functions,
|
|
||||||
#hicpp-static-assert,
|
|
||||||
#hicpp-undelegated-constructor,
|
|
||||||
#hicpp-uppercase-literal-suffix,
|
|
||||||
#hicpp-use-auto,
|
|
||||||
#hicpp-use-emplace,
|
|
||||||
#hicpp-use-equals-default,
|
|
||||||
#hicpp-use-equals-delete,
|
|
||||||
#hicpp-use-noexcept,
|
|
||||||
#hicpp-use-nullptr,
|
|
||||||
#hicpp-use-override,
|
|
||||||
#hicpp-vararg,
|
|
||||||
#modernize-avoid-bind,
|
|
||||||
#modernize-avoid-c-arrays,
|
|
||||||
#modernize-concat-nested-namespaces,
|
|
||||||
#modernize-deprecated-headers,
|
|
||||||
#modernize-deprecated-ios-base-aliases,
|
|
||||||
#modernize-loop-convert,
|
|
||||||
#modernize-make-shared,
|
|
||||||
#modernize-make-unique,
|
|
||||||
#modernize-pass-by-value,
|
|
||||||
#modernize-raw-string-literal,
|
|
||||||
#modernize-redundant-void-arg,
|
|
||||||
#modernize-replace-auto-ptr,
|
|
||||||
#modernize-replace-disallow-copy-and-assign-macro,
|
|
||||||
#modernize-replace-random-shuffle,
|
|
||||||
#modernize-return-braced-init-list,
|
|
||||||
#modernize-shrink-to-fit,
|
|
||||||
#modernize-unary-static-assert,
|
|
||||||
#modernize-use-auto,
|
|
||||||
#modernize-use-bool-literals,
|
|
||||||
#modernize-use-default-member-init,
|
|
||||||
#modernize-use-emplace,
|
|
||||||
#modernize-use-equals-default,
|
|
||||||
#modernize-use-equals-delete,
|
|
||||||
#modernize-use-nodiscard,
|
|
||||||
#modernize-use-noexcept,
|
|
||||||
#modernize-use-nullptr,
|
|
||||||
#modernize-use-override,
|
|
||||||
#modernize-use-trailing-return-type,
|
|
||||||
#modernize-use-transparent-functors,
|
|
||||||
#modernize-use-uncaught-exceptions,
|
|
||||||
#modernize-use-using,
|
|
||||||
#performance-faster-string-find,
|
|
||||||
#performance-for-range-copy,
|
|
||||||
#performance-implicit-conversion-in-loop,
|
|
||||||
#performance-inefficient-algorithm,
|
|
||||||
#performance-inefficient-string-concatenation,
|
|
||||||
#performance-inefficient-vector-operation,
|
|
||||||
#performance-move-const-arg,
|
|
||||||
#performance-move-constructor-init,
|
|
||||||
#performance-no-automatic-move,
|
|
||||||
#performance-no-int-to-ptr,
|
|
||||||
#performance-noexcept-move-constructor,
|
|
||||||
#performance-trivially-destructible,
|
|
||||||
#performance-type-promotion-in-math-fn,
|
|
||||||
#performance-unnecessary-copy-initialization,
|
|
||||||
#performance-unnecessary-value-param,
|
|
||||||
#portability-restrict-system-includes,
|
|
||||||
#portability-simd-intrinsics,
|
|
||||||
#readability-avoid-const-params-in-decls,
|
|
||||||
#readability-braces-around-statements,
|
|
||||||
#readability-const-return-type,
|
|
||||||
#readability-container-contains,
|
|
||||||
#readability-container-data-pointer,
|
|
||||||
#readability-container-size-empty,
|
|
||||||
#readability-convert-member-functions-to-static,
|
|
||||||
#readability-delete-null-pointer,
|
|
||||||
#readability-duplicate-include,
|
|
||||||
#readability-else-after-return,
|
|
||||||
#readability-function-cognitive-complexity,
|
|
||||||
#readability-function-size,
|
|
||||||
#readability-identifier-length,
|
|
||||||
#readability-identifier-naming,
|
|
||||||
#readability-implicit-bool-conversion,
|
|
||||||
#readability-inconsistent-declaration-parameter-name,
|
|
||||||
#readability-isolate-declaration,
|
|
||||||
#readability-magic-numbers,
|
|
||||||
#readability-make-member-function-const,
|
|
||||||
#readability-misleading-indentation,
|
|
||||||
#readability-misplaced-array-index,
|
|
||||||
#readability-named-parameter,
|
|
||||||
#readability-non-const-parameter,
|
|
||||||
#readability-qualified-auto,
|
|
||||||
#readability-redundant-access-specifiers,
|
|
||||||
#readability-redundant-control-flow,
|
|
||||||
#readability-redundant-declaration,
|
|
||||||
#readability-redundant-function-ptr-dereference,
|
|
||||||
#readability-redundant-member-init,
|
|
||||||
#readability-redundant-preprocessor,
|
|
||||||
#readability-redundant-smartptr-get,
|
|
||||||
#readability-redundant-string-cstr,
|
|
||||||
#readability-redundant-string-init,
|
|
||||||
#readability-simplify-boolean-expr,
|
|
||||||
#readability-simplify-subscript-expr,
|
|
||||||
#readability-static-accessed-through-instance,
|
|
||||||
#readability-static-definition-in-anonymous-namespace,
|
|
||||||
#readability-string-compare,
|
|
||||||
#readability-suspicious-call-argument,
|
|
||||||
#readability-uniqueptr-delete-release,
|
|
||||||
#readability-uppercase-literal-suffix,
|
|
||||||
#readability-use-anyofallof
|
|
||||||
"
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
root = true
|
|
||||||
# Don't set line endings to avoid conflict with core.autocrlf flag.
|
|
||||||
# Line endings on checkout/checkin are controlled by .gitattributes file.
|
|
||||||
[*]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
|
||||||
* text=auto
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Default owner
|
|
||||||
* @dbaileychess derekbailey@google.com
|
|
||||||
|
|
||||||
# Prevent modification of this file
|
|
||||||
.github/CODEOWNERS @dbaileychess derekbailey@google.com
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
Thank you for submitting an issue!
|
|
||||||
|
|
||||||
Please make sure you include the names of the affected language(s), compiler version(s), operating system version(s), and FlatBuffers version(s) in your issue title.
|
|
||||||
|
|
||||||
This helps us get the correct maintainers to look at your issue. Here are examples of good titles:
|
|
||||||
|
|
||||||
- Crash when accessing FlatBuffer [C++, gcc 4.8, OS X, master]
|
|
||||||
- Flatc converts a protobuf 'bytes' field to 'string' in fbs schema file [all languages, FlatBuffers 1.4]
|
|
||||||
|
|
||||||
Include other details as appropriate.
|
|
||||||
|
|
||||||
Thanks!
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
name: 404 Doc
|
|
||||||
about: To fix broken documentation links
|
|
||||||
title: "[Doc 404]"
|
|
||||||
labels: documentation
|
|
||||||
assignees: dbaileychess
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Target URL:
|
|
||||||
[Optional] Source Site:
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
Thank you for submitting a PR!
|
|
||||||
|
|
||||||
Please delete this standard text once you've created your own description.
|
|
||||||
|
|
||||||
If you make changes to any of the code generators (`src/idl_gen*`) be sure to
|
|
||||||
[build](https://google.github.io/flatbuffers/flatbuffers_guide_building.html) your project, as it will generate code based on the changes. If necessary
|
|
||||||
the code generation script can be directly run (`scripts/generate_code.py`),
|
|
||||||
requires Python3. This allows us to better see the effect of the PR.
|
|
||||||
|
|
||||||
If your PR includes C++ code, please adhere to the
|
|
||||||
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html),
|
|
||||||
and don't forget we try to support older compilers (e.g. VS2010, GCC 4.6.3),
|
|
||||||
so only some C++11 support is available.
|
|
||||||
|
|
||||||
For any C++ changes, please make sure to run `sh scripts/clang-format-git.sh`
|
|
||||||
|
|
||||||
Include other details as appropriate.
|
|
||||||
|
|
||||||
Thanks!
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
# Configuration for Auto Labeler during pull request
|
|
||||||
#
|
|
||||||
# See https://github.com/actions/labeler for file format
|
|
||||||
# and https://github.com/google/flatbuffers/labels for a list of valid labels
|
|
||||||
#
|
|
||||||
# See .github/workflows/label.yml for Github Action workflow script
|
|
||||||
|
|
||||||
"c#":
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.cs'
|
|
||||||
- 'net/**/*'
|
|
||||||
- 'tests/FlatBuffers.Test/**/*'
|
|
||||||
- 'tests/FlatBuffers.Benchmarks/**/*'
|
|
||||||
- 'src/idl_gen_csharp.cpp'
|
|
||||||
|
|
||||||
swift:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.swift'
|
|
||||||
- 'swift/**/*'
|
|
||||||
- 'tests/swift/**'
|
|
||||||
- 'src/idl_gen_swift.cpp'
|
|
||||||
|
|
||||||
nim:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.nim'
|
|
||||||
- 'nim/**/*'
|
|
||||||
- 'src/idl_gen_nim.cpp'
|
|
||||||
- 'src/bfbs_gen_nim.cpp'
|
|
||||||
|
|
||||||
javascript:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.js'
|
|
||||||
- 'src/idl_gen_ts.cpp'
|
|
||||||
|
|
||||||
typescript:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.ts'
|
|
||||||
- 'src/idl_gen_ts.cpp'
|
|
||||||
- 'grpc/flatbuffers-js-grpc/**/*.ts'
|
|
||||||
|
|
||||||
golang:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.go'
|
|
||||||
- 'src/idl_gen_go.cpp'
|
|
||||||
|
|
||||||
python:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.py'
|
|
||||||
- 'src/idl_gen_python.cpp'
|
|
||||||
|
|
||||||
java:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.java'
|
|
||||||
- 'src/idl_gen_java.cpp'
|
|
||||||
|
|
||||||
kotlin:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.kt'
|
|
||||||
- 'src/idl_gen_kotlin.cpp'
|
|
||||||
- 'src/idl_gen_kotlin_kmp.cpp'
|
|
||||||
|
|
||||||
lua:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.lua'
|
|
||||||
- 'lua/**/*'
|
|
||||||
- 'src/bfbs_gen_lua.cpp'
|
|
||||||
|
|
||||||
lobster:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.lobster'
|
|
||||||
- 'src/idl_gen_lobster.cpp'
|
|
||||||
|
|
||||||
php:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.php'
|
|
||||||
- 'src/idl_gen_php.cpp'
|
|
||||||
|
|
||||||
rust:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.rs'
|
|
||||||
- 'rust/**/*'
|
|
||||||
- 'src/idl_gen_rust.cpp'
|
|
||||||
|
|
||||||
dart:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.dart'
|
|
||||||
- 'src/idl_gen_dart.cpp'
|
|
||||||
|
|
||||||
"c++":
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.cc'
|
|
||||||
- '**/*.cpp'
|
|
||||||
- '**/*.h'
|
|
||||||
|
|
||||||
json:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '**/*.json'
|
|
||||||
- 'src/idl_gen_json_schema.cpp'
|
|
||||||
|
|
||||||
codegen:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- 'src/**/*'
|
|
||||||
|
|
||||||
documentation:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- 'docs/**/*'
|
|
||||||
- '**/*.md'
|
|
||||||
|
|
||||||
CI:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- '.github/**/*'
|
|
||||||
- '.bazelci/**/*'
|
|
||||||
|
|
||||||
grpc:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- 'grpc/**/*'
|
|
||||||
- 'src/idl_gen_grpc.cpp'
|
|
||||||
@@ -1,643 +0,0 @@
|
|||||||
name: CI
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
on:
|
|
||||||
# For manual tests.
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "*" # new tag version, like `0.8.4` or else
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
schedule:
|
|
||||||
# Run daily at 4:45 A.M. to catch dependencies that break us.
|
|
||||||
- cron: '45 4 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-linux:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
outputs:
|
|
||||||
digests-gcc: ${{ steps.hash-gcc.outputs.hashes }}
|
|
||||||
digests-clang: ${{ steps.hash-clang.outputs.hashes }}
|
|
||||||
name: Build Linux
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
cxx: [g++-13, clang++-18]
|
|
||||||
fail-fast: false
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: cmake
|
|
||||||
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_STATIC_FLATC=ON .
|
|
||||||
- name: build
|
|
||||||
run: make -j
|
|
||||||
- name: test
|
|
||||||
run: ./flattests
|
|
||||||
- name: make flatc executable
|
|
||||||
run: |
|
|
||||||
chmod +x flatc
|
|
||||||
./flatc --version
|
|
||||||
- name: upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: Linux flatc binary ${{ matrix.cxx }}
|
|
||||||
path: flatc
|
|
||||||
# Below if only for release.
|
|
||||||
- name: Zip file
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
run: zip Linux.flatc.binary.${{ matrix.cxx }}.zip flatc
|
|
||||||
- name: Release zip file
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
|
||||||
files: Linux.flatc.binary.${{ matrix.cxx }}.zip
|
|
||||||
- name: Generate SLSA subjects - clang
|
|
||||||
if: matrix.cxx == 'clang++-18' && startsWith(github.ref, 'refs/tags/')
|
|
||||||
id: hash-clang
|
|
||||||
run: echo "hashes=$(sha256sum Linux.flatc.binary.${{ matrix.cxx }}.zip | base64 -w0)" >> $GITHUB_OUTPUT
|
|
||||||
- name: Generate SLSA subjects - gcc
|
|
||||||
if: matrix.cxx == 'g++-13' && startsWith(github.ref, 'refs/tags/')
|
|
||||||
id: hash-gcc
|
|
||||||
run: echo "hashes=$(sha256sum Linux.flatc.binary.${{ matrix.cxx }}.zip | base64 -w0)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
build-linux-no-file-tests:
|
|
||||||
name: Build Linux with -DFLATBUFFERS_NO_FILE_TESTS
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: cmake
|
|
||||||
run: CXX=clang++-18 cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_CXX_FLAGS="-DFLATBUFFERS_NO_FILE_TESTS" .
|
|
||||||
- name: build
|
|
||||||
run: make -j
|
|
||||||
- name: test
|
|
||||||
run: ./flattests
|
|
||||||
|
|
||||||
build-linux-out-of-source:
|
|
||||||
name: Build Linux with out-of-source build location
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: make build directory
|
|
||||||
run: mkdir build
|
|
||||||
- name: cmake
|
|
||||||
working-directory: build
|
|
||||||
run: >
|
|
||||||
CXX=clang++-18 cmake .. -G "Unix Makefiles" -DFLATBUFFERS_STRICT_MODE=ON
|
|
||||||
-DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_CPP_STD=17
|
|
||||||
- name: build
|
|
||||||
working-directory: build
|
|
||||||
run: make -j
|
|
||||||
- name: test
|
|
||||||
working-directory: build
|
|
||||||
run: pwd && ./flattests
|
|
||||||
- name: test C++17
|
|
||||||
working-directory: build
|
|
||||||
run: ./flattests_cpp17
|
|
||||||
|
|
||||||
build-linux-cpp-std:
|
|
||||||
name: Build Linux C++
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
std: [11, 14, 17, 20, 23]
|
|
||||||
cxx: [g++-13, clang++-18]
|
|
||||||
exclude:
|
|
||||||
# Clang++15 10.3.0 stdlibc++ doesn't fully support std 23
|
|
||||||
- cxx: clang++-18
|
|
||||||
std: 23
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: cmake
|
|
||||||
run: >
|
|
||||||
CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles"
|
|
||||||
-DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON
|
|
||||||
-DFLATBUFFERS_CPP_STD=${{ matrix.std }}
|
|
||||||
-DFLATBUFFERS_BUILD_CPP17=${{ matrix.std >= 17 && 'On' || 'Off'}}
|
|
||||||
- name: build
|
|
||||||
run: make -j
|
|
||||||
- name: test
|
|
||||||
run: ./flattests
|
|
||||||
- name: test C++17
|
|
||||||
if: matrix.std >= 17
|
|
||||||
run: ./flattests_cpp17
|
|
||||||
|
|
||||||
build-cpp-std:
|
|
||||||
name: Build Windows C++
|
|
||||||
runs-on: windows-2022
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
std: [11, 14, 17, 20, 23]
|
|
||||||
fail-fast: false
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Add msbuild to PATH
|
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
- name: cmake
|
|
||||||
run: >
|
|
||||||
cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
|
|
||||||
-DFLATBUFFERS_STRICT_MODE=ON
|
|
||||||
-DFLATBUFFERS_CPP_STD=${{ matrix.std }}
|
|
||||||
-DFLATBUFFERS_BUILD_CPP17=${{ matrix.std >= 17 && 'On' || 'Off'}}
|
|
||||||
- name: build
|
|
||||||
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
|
|
||||||
- name: test
|
|
||||||
run: Release\flattests.exe
|
|
||||||
- name: test C++17
|
|
||||||
if: matrix.std >= 17
|
|
||||||
run: Release\flattests_cpp17.exe
|
|
||||||
|
|
||||||
build-windows:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
outputs:
|
|
||||||
digests: ${{ steps.hash.outputs.hashes }}
|
|
||||||
name: Build Windows 2022
|
|
||||||
runs-on: windows-2022
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Add msbuild to PATH
|
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
- name: cmake
|
|
||||||
run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
|
|
||||||
- name: build
|
|
||||||
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
|
|
||||||
- name: test
|
|
||||||
run: Release\flattests.exe
|
|
||||||
- name: upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: Windows flatc binary
|
|
||||||
path: Release\flatc.exe
|
|
||||||
# Below if only for release.
|
|
||||||
- name: Zip file
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
run: move Release/flatc.exe . && Compress-Archive flatc.exe Windows.flatc.binary.zip
|
|
||||||
- name: Release binary
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
|
||||||
files: Windows.flatc.binary.zip
|
|
||||||
- name: Generate SLSA subjects
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
id: hash
|
|
||||||
shell: bash
|
|
||||||
run: echo "hashes=$(sha256sum Windows.flatc.binary.zip | base64 -w0)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
build-dotnet-windows:
|
|
||||||
name: Build .NET Windows
|
|
||||||
runs-on: windows-2022
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
configuration: [
|
|
||||||
'',
|
|
||||||
'-p:UnsafeByteBuffer=true',
|
|
||||||
'-p:EnableSpanT=true,UnsafeByteBuffer=true'
|
|
||||||
]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Setup .NET Core SDK
|
|
||||||
uses: actions/setup-dotnet@v5
|
|
||||||
with:
|
|
||||||
dotnet-version: '8.0.x'
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
cd tests\FlatBuffers.Test
|
|
||||||
dotnet new sln --force --name FlatBuffers.Test --format sln
|
|
||||||
dotnet sln FlatBuffers.Test.sln add FlatBuffers.Test.csproj
|
|
||||||
dotnet build -c Release ${{matrix.configuration}} FlatBuffers.Test.sln
|
|
||||||
- name: Run net6.0
|
|
||||||
run: |
|
|
||||||
cd tests\FlatBuffers.Test\bin\Release\net6.0
|
|
||||||
dir
|
|
||||||
.\FlatBuffers.Test.exe
|
|
||||||
- name: Run net8.0
|
|
||||||
run: |
|
|
||||||
cd tests\FlatBuffers.Test\bin\Release\net8.0
|
|
||||||
.\FlatBuffers.Test.exe
|
|
||||||
|
|
||||||
build-mac-intel:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
outputs:
|
|
||||||
digests: ${{ steps.hash.outputs.hashes }}
|
|
||||||
name: Build Mac (for Intel)
|
|
||||||
runs-on: macos-15-intel
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: cmake
|
|
||||||
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
|
|
||||||
- name: build
|
|
||||||
run: xcodebuild -toolchain clang -configuration Release -target flattests
|
|
||||||
- name: check that the binary is x86_64
|
|
||||||
run: |
|
|
||||||
info=$(file Release/flatc)
|
|
||||||
echo $info
|
|
||||||
echo $info | grep "Mach-O 64-bit executable x86_64"
|
|
||||||
- name: test
|
|
||||||
run: Release/flattests
|
|
||||||
- name: make flatc executable
|
|
||||||
run: |
|
|
||||||
chmod +x Release/flatc
|
|
||||||
Release/flatc --version
|
|
||||||
- name: upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: Mac flatc binary Intel
|
|
||||||
path: Release/flatc
|
|
||||||
# Below if only for release.
|
|
||||||
- name: Zip file
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
run: mv Release/flatc . && zip MacIntel.flatc.binary.zip flatc
|
|
||||||
- name: Release binary
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
|
||||||
files: MacIntel.flatc.binary.zip
|
|
||||||
- name: Generate SLSA subjects
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
id: hash
|
|
||||||
run: echo "hashes=$(shasum -a 256 MacIntel.flatc.binary.zip | base64)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
build-mac-universal:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
outputs:
|
|
||||||
digests: ${{ steps.hash.outputs.hashes }}
|
|
||||||
name: Build Mac (universal build)
|
|
||||||
runs-on: macos-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: cmake
|
|
||||||
run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON .
|
|
||||||
- name: build
|
|
||||||
run: xcodebuild -toolchain clang -configuration Release -target flattests
|
|
||||||
- name: check that the binary is "universal"
|
|
||||||
run: |
|
|
||||||
info=$(file Release/flatc)
|
|
||||||
echo $info
|
|
||||||
echo $info | grep "Mach-O universal binary with 2 architectures"
|
|
||||||
- name: test
|
|
||||||
run: Release/flattests
|
|
||||||
- name: make flatc executable
|
|
||||||
run: |
|
|
||||||
chmod +x Release/flatc
|
|
||||||
Release/flatc --version
|
|
||||||
- name: upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: Mac flatc binary Universal
|
|
||||||
path: Release/flatc
|
|
||||||
# Below if only for release.
|
|
||||||
- name: Zip file
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
run: mv Release/flatc . && zip Mac.flatc.binary.zip flatc
|
|
||||||
- name: Release binary
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
|
||||||
files: Mac.flatc.binary.zip
|
|
||||||
- name: Generate SLSA subjects
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
id: hash
|
|
||||||
run: echo "hashes=$(shasum -a 256 Mac.flatc.binary.zip | base64)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
build-android:
|
|
||||||
name: Build Android (on Linux)
|
|
||||||
if: false #disabled due to continual failure
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: set up Java
|
|
||||||
uses: actions/setup-java@v5
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 17
|
|
||||||
- name: set up Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v5
|
|
||||||
- name: set up flatc
|
|
||||||
run: |
|
|
||||||
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON .
|
|
||||||
make -j
|
|
||||||
echo "${PWD}" >> $GITHUB_PATH
|
|
||||||
- name: build
|
|
||||||
working-directory: android
|
|
||||||
run: gradle clean build
|
|
||||||
|
|
||||||
build-generator:
|
|
||||||
name: Check Generated Code
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
cxx: [g++-13, clang++-18]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: cmake
|
|
||||||
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
|
||||||
- name: Generate
|
|
||||||
run: scripts/check_generate_code.py
|
|
||||||
- name: Generate gRPC
|
|
||||||
run: scripts/check-grpc-generated-code.py
|
|
||||||
|
|
||||||
build-generator-windows:
|
|
||||||
name: Check Generated Code on Windows
|
|
||||||
runs-on: windows-2022
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Add msbuild to PATH
|
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
- name: cmake
|
|
||||||
run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON .
|
|
||||||
- name: build
|
|
||||||
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
|
|
||||||
- name: Generate
|
|
||||||
run: python3 scripts/check_generate_code.py --flatc Release\flatc.exe
|
|
||||||
- name: Generate gRPC
|
|
||||||
run: python3 scripts/check-grpc-generated-code.py --flatc Release\flatc.exe
|
|
||||||
|
|
||||||
build-benchmarks:
|
|
||||||
name: Build Benchmarks (on Linux)
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
cxx: [g++-13]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: cmake
|
|
||||||
run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_CXX_FLAGS="-Wno-unused-parameter -fno-aligned-new" -DFLATBUFFERS_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
|
||||||
- name: Run benchmarks
|
|
||||||
run: ./flatbenchmark --benchmark_repetitions=5 --benchmark_display_aggregates_only=true --benchmark_out_format=console --benchmark_out=benchmarks/results_${{matrix.cxx}}
|
|
||||||
- name: Upload benchmarks results
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: Linux flatbenchmark results ${{matrix.cxx}}
|
|
||||||
path: benchmarks/results_${{matrix.cxx}}
|
|
||||||
|
|
||||||
build-java:
|
|
||||||
name: Build Java
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: test
|
|
||||||
working-directory: java
|
|
||||||
run: mvn test
|
|
||||||
|
|
||||||
build-kotlin-macos:
|
|
||||||
name: Build Kotlin MacOS
|
|
||||||
runs-on: macos-15
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: set up Java
|
|
||||||
uses: actions/setup-java@v5
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 17
|
|
||||||
- name: set up Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v5
|
|
||||||
- name: Build flatc
|
|
||||||
run: |
|
|
||||||
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
|
|
||||||
make -j
|
|
||||||
echo "${PWD}" >> $GITHUB_PATH
|
|
||||||
- name: Build
|
|
||||||
working-directory: kotlin
|
|
||||||
run: ./gradlew clean iosSimulatorArm64Test macosX64Test macosArm64Test
|
|
||||||
|
|
||||||
build-kotlin-linux:
|
|
||||||
name: Build Kotlin Linux
|
|
||||||
if: false #disabled due to continual failure
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: set up Java
|
|
||||||
uses: actions/setup-java@v5
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 17
|
|
||||||
- name: set up Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v5
|
|
||||||
- name: Build flatc
|
|
||||||
run: |
|
|
||||||
cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF .
|
|
||||||
make -j
|
|
||||||
echo "${PWD}" >> $GITHUB_PATH
|
|
||||||
- name: Build
|
|
||||||
working-directory: kotlin
|
|
||||||
# we are using docker's version of gradle
|
|
||||||
# so no need for wrapper validation or user
|
|
||||||
# gradlew
|
|
||||||
run: gradle jvmMainClasses jvmTest jsTest jsBrowserTest
|
|
||||||
|
|
||||||
build-rust-linux:
|
|
||||||
name: Build Rust Linux
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: test
|
|
||||||
working-directory: tests
|
|
||||||
run: bash RustTest.sh
|
|
||||||
|
|
||||||
build-rust-windows:
|
|
||||||
name: Build Rust Windows
|
|
||||||
runs-on: windows-2022
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: test
|
|
||||||
working-directory: tests
|
|
||||||
run: ./RustTest.bat
|
|
||||||
|
|
||||||
build-python:
|
|
||||||
name: Build Python
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: flatc
|
|
||||||
# FIXME: make test script not rely on flatc
|
|
||||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
|
||||||
- name: test
|
|
||||||
working-directory: tests
|
|
||||||
run: bash PythonTest.sh
|
|
||||||
|
|
||||||
build-go:
|
|
||||||
name: Build Go
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: flatc
|
|
||||||
# FIXME: make test script not rely on flatc
|
|
||||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
|
||||||
- name: test
|
|
||||||
working-directory: tests
|
|
||||||
run: bash GoTest.sh
|
|
||||||
|
|
||||||
build-php:
|
|
||||||
name: Build PHP
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: flatc
|
|
||||||
# FIXME: make test script not rely on flatc
|
|
||||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
|
||||||
- name: test
|
|
||||||
working-directory: tests
|
|
||||||
run: |
|
|
||||||
php phpTest.php
|
|
||||||
sh phpUnionVectorTest.sh
|
|
||||||
|
|
||||||
build-swift:
|
|
||||||
name: Test Swift Linux
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
swift: ["6.0", "6.1", "6.2"]
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: swift-actions/setup-swift@v2
|
|
||||||
with:
|
|
||||||
swift-version: ${{ matrix.swift }}
|
|
||||||
- name: Get swift version
|
|
||||||
run: swift --version
|
|
||||||
- name: test
|
|
||||||
run: swift test
|
|
||||||
|
|
||||||
build-swift-windows:
|
|
||||||
name: Test swift windows
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: SwiftyLab/setup-swift@latest
|
|
||||||
with:
|
|
||||||
swift-version: '6.1'
|
|
||||||
- run: swift build
|
|
||||||
- run: swift test
|
|
||||||
|
|
||||||
build-swift-wasm:
|
|
||||||
name: Test Swift Wasm
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: swift-actions/setup-swift@v2
|
|
||||||
with:
|
|
||||||
swift-version: 6.2.1
|
|
||||||
- uses: bytecodealliance/actions/wasmtime/setup@v1
|
|
||||||
- name: Install Swift SDK
|
|
||||||
run: swift sdk install https://download.swift.org/swift-6.2.1-release/wasm-sdk/swift-6.2.1-RELEASE/swift-6.2.1-RELEASE_wasm.artifactbundle.tar.gz --checksum 482b9f95462b87bedfafca94a092cf9ec4496671ca13b43745097122d20f18af
|
|
||||||
- name: Test
|
|
||||||
working-directory: tests/swift/Wasm.tests
|
|
||||||
run: |
|
|
||||||
swift sdk list
|
|
||||||
swift build --build-tests --swift-sdk swift-6.2.1-RELEASE_wasm
|
|
||||||
wasmtime --dir . .build/wasm32-unknown-wasip1/debug/FlatBuffers.Test.Swift.WasmPackageTests.xctest --testing-library swift-testing
|
|
||||||
|
|
||||||
build-ts:
|
|
||||||
name: Build TS
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: flatc
|
|
||||||
# FIXME: make test script not rely on flatc
|
|
||||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
|
|
||||||
- name: pnpm
|
|
||||||
run: npm install -g pnpm
|
|
||||||
- name: deps
|
|
||||||
run: pnpm i
|
|
||||||
- name: compile
|
|
||||||
run: pnpm compile
|
|
||||||
- name: test
|
|
||||||
working-directory: tests/ts
|
|
||||||
run: |
|
|
||||||
python3 TypeScriptTest.py
|
|
||||||
|
|
||||||
build-dart:
|
|
||||||
name: Build Dart
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: dart-lang/setup-dart@v1
|
|
||||||
with:
|
|
||||||
sdk: stable
|
|
||||||
- name: flatc
|
|
||||||
# FIXME: make test script not rely on flatc
|
|
||||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j
|
|
||||||
- name: test
|
|
||||||
working-directory: tests
|
|
||||||
run: bash DartTest.sh
|
|
||||||
|
|
||||||
build-nim:
|
|
||||||
name: Build Nim
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: flatc
|
|
||||||
# FIXME: make test script not rely on flatc
|
|
||||||
run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j
|
|
||||||
- uses: jiro4989/setup-nim-action@v2
|
|
||||||
- name: install library
|
|
||||||
working-directory: nim
|
|
||||||
run: nimble -y develop && nimble install
|
|
||||||
- name: test
|
|
||||||
working-directory: tests/nim
|
|
||||||
run: python3 testnim.py
|
|
||||||
|
|
||||||
bazel:
|
|
||||||
name: Bazel
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
# Explicitly use 8.5.1 until we can update or https://github.com/actions/runner-images/issues/13564 is fixed.
|
|
||||||
- name: Set env
|
|
||||||
run: >
|
|
||||||
echo "USE_BAZEL_VERSION=8.5.1" >> $GITHUB_ENV
|
|
||||||
- name: bazel build
|
|
||||||
run: >
|
|
||||||
bazel build
|
|
||||||
//:flatc
|
|
||||||
//:flatbuffers
|
|
||||||
//tests:flatbuffers_test
|
|
||||||
- name: bazel test
|
|
||||||
run: >
|
|
||||||
bazel test
|
|
||||||
//tests:flatbuffers_test
|
|
||||||
|
|
||||||
release-digests:
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
needs: [build-linux, build-windows, build-mac-intel, build-mac-universal]
|
|
||||||
outputs:
|
|
||||||
digests: ${{ steps.hash.outputs.digests }}
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Merge results
|
|
||||||
id: hash
|
|
||||||
env:
|
|
||||||
LINUXGCC_DIGESTS: "${{ needs.build-linux.outputs.digests-gcc }}"
|
|
||||||
LINUXCLANG_DIGESTS: "${{ needs.build-linux.outputs.digests-clang }}"
|
|
||||||
MAC_DIGESTS: "${{ needs.build-mac-universal.outputs.digests }}"
|
|
||||||
MACINTEL_DIGESTS: "${{ needs.build-mac-intel.outputs.digests }}"
|
|
||||||
WINDOWS_DIGESTS: "${{ needs.build-windows.outputs.digests }}"
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
echo "$LINUXGCC_DIGESTS" | base64 -d > checksums.txt
|
|
||||||
echo "$LINUXCLANG_DIGESTS" | base64 -d >> checksums.txt
|
|
||||||
echo "$MAC_DIGESTS" | base64 -d >> checksums.txt
|
|
||||||
echo "$MACINTEL_DIGESTS" | base64 -d >> checksums.txt
|
|
||||||
echo "$WINDOWS_DIGESTS" | base64 -d >> checksums.txt
|
|
||||||
echo "digests=$(cat checksums.txt | base64 -w0)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
provenance:
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
needs: [release-digests]
|
|
||||||
permissions:
|
|
||||||
actions: read # To read the workflow path.
|
|
||||||
id-token: write # To sign the provenance.
|
|
||||||
contents: write # To add assets to a release.
|
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
|
|
||||||
with:
|
|
||||||
base64-subjects: "${{ needs.release-digests.outputs.digests }}"
|
|
||||||
upload-assets: true # Optional: Upload to a new release
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
name: docs
|
|
||||||
on:
|
|
||||||
# For manual pushes.
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
# Pushes to main that touch the documentation directory.
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths:
|
|
||||||
- 'docs/**'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Configure Git Credentials
|
|
||||||
run: |
|
|
||||||
git config user.name github-actions[bot]
|
|
||||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
|
||||||
- uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: 3.x
|
|
||||||
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
|
||||||
- uses: actions/cache@v5
|
|
||||||
with:
|
|
||||||
key: mkdocs-material-${{ env.cache_id }}
|
|
||||||
path: .cache
|
|
||||||
restore-keys: |
|
|
||||||
mkdocs-material-
|
|
||||||
- run: pip install mkdocs-material
|
|
||||||
- run: pip install mkdocs-redirects
|
|
||||||
- run: mkdocs gh-deploy --force -f docs/mkdocs.yml
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# This workflow will triage pull requests and apply a label based on the
|
|
||||||
# paths that are modified in the pull request.
|
|
||||||
#
|
|
||||||
# To use this workflow, you will need to set up a .github/labeler.yml
|
|
||||||
# file with configuration. For more information, see:
|
|
||||||
# https://github.com/actions/labeler
|
|
||||||
|
|
||||||
name: Labeler
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
on: [pull_request_target]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
label:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/labeler@v6
|
|
||||||
with:
|
|
||||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
name: OSS-Fuzz
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths:
|
|
||||||
- include/**
|
|
||||||
- src/**
|
|
||||||
- tests/**.cpp
|
|
||||||
- tests/**.h
|
|
||||||
jobs:
|
|
||||||
Fuzzing:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Build Fuzzers
|
|
||||||
id: build
|
|
||||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
|
||||||
with:
|
|
||||||
oss-fuzz-project-name: 'flatbuffers'
|
|
||||||
language: c++
|
|
||||||
- name: Run Fuzzers
|
|
||||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
|
||||||
with:
|
|
||||||
oss-fuzz-project-name: 'flatbuffers'
|
|
||||||
language: c++
|
|
||||||
fuzz-seconds: 60
|
|
||||||
- name: Upload Crash
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
if: failure() && steps.build.outcome == 'success'
|
|
||||||
with:
|
|
||||||
name: artifacts
|
|
||||||
path: ./out/artifacts
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
name: Release
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
on:
|
|
||||||
# For manual tests.
|
|
||||||
workflow_dispatch:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish-npm:
|
|
||||||
name: Publish NPM
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: '20.x'
|
|
||||||
registry-url: 'https://registry.npmjs.org'
|
|
||||||
|
|
||||||
- run: npm publish
|
|
||||||
env:
|
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
publish-pypi:
|
|
||||||
name: Publish PyPi
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: ./python
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: '3.10'
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: |
|
|
||||||
python3 -m pip install --upgrade pip
|
|
||||||
python3 -m pip install build twine
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
python3 -m build .
|
|
||||||
|
|
||||||
- name: Upload to PyPi
|
|
||||||
run: |
|
|
||||||
python3 -m twine upload dist/*
|
|
||||||
env:
|
|
||||||
TWINE_USERNAME: __token__
|
|
||||||
TWINE_PASSWORD: ${{ secrets.TWINE_TOKEN }}
|
|
||||||
|
|
||||||
publish-nuget:
|
|
||||||
name: Publish NuGet
|
|
||||||
runs-on: windows-latest
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: ./net/flatbuffers
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: actions/setup-dotnet@v5
|
|
||||||
with:
|
|
||||||
dotnet-version: '8.0.x'
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
dotnet build Google.FlatBuffers.csproj -c Release
|
|
||||||
|
|
||||||
- name: Pack
|
|
||||||
run: |
|
|
||||||
dotnet pack Google.FlatBuffers.csproj -c Release
|
|
||||||
|
|
||||||
- name: Upload to NuGet
|
|
||||||
run: |
|
|
||||||
dotnet nuget push .\bin\Release\Google.FlatBuffers.*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
|
|
||||||
|
|
||||||
publish-maven:
|
|
||||||
name: Publish Maven
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: ./java
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Set up Maven Central Repository
|
|
||||||
uses: actions/setup-java@v5
|
|
||||||
with:
|
|
||||||
java-version: '11'
|
|
||||||
distribution: 'adopt'
|
|
||||||
cache: 'maven'
|
|
||||||
server-id: ossrh
|
|
||||||
server-username: OSSRH_USERNAME
|
|
||||||
server-password: OSSRH_PASSWORD
|
|
||||||
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
|
|
||||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE # this needs to be an env var
|
|
||||||
|
|
||||||
- name: Publish Maven
|
|
||||||
run: mvn --batch-mode clean deploy
|
|
||||||
env:
|
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USER_V2 }}
|
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN_V2 }}
|
|
||||||
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
|
|
||||||
|
|
||||||
publish-maven-kotlin:
|
|
||||||
name: Publish Maven - Kotlin
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: ./kotlin
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Set up Maven Central Repository
|
|
||||||
uses: actions/setup-java@v5
|
|
||||||
with:
|
|
||||||
java-version: '11'
|
|
||||||
distribution: 'adopt'
|
|
||||||
cache: 'maven'
|
|
||||||
server-id: ossrh
|
|
||||||
server-username: OSSRH_USERNAME
|
|
||||||
server-password: OSSRH_PASSWORD
|
|
||||||
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
|
|
||||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE # this needs to be an env var
|
|
||||||
|
|
||||||
- name: Publish Kotlin Library on Maven
|
|
||||||
run: ./gradlew publishAllPublicationsToSonatypeRepository
|
|
||||||
env:
|
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USER_V2 }}
|
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN_V2 }}
|
|
||||||
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
|
|
||||||
|
|
||||||
|
|
||||||
publish-crates:
|
|
||||||
name: Publish crates.io
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: stable
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Publish Flatbuffers
|
|
||||||
uses: katyo/publish-crates@v2
|
|
||||||
with:
|
|
||||||
path: ./rust/flatbuffers
|
|
||||||
registry-token: ${{ secrets.CARGO_TOKEN }}
|
|
||||||
|
|
||||||
- name: Publish Flexbuffers
|
|
||||||
uses: katyo/publish-crates@v2
|
|
||||||
with:
|
|
||||||
path: ./rust/flexbuffers
|
|
||||||
registry-token: ${{ secrets.CARGO_TOKEN }}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
name: Mark stale issues and pull requests
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
on:
|
|
||||||
# For manual tests.
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: "30 20 * * *"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v10
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
operations-per-run: 500
|
|
||||||
exempt-all-milestones: true
|
|
||||||
remove-stale-when-updated: true
|
|
||||||
|
|
||||||
stale-issue-message: 'This issue is stale because it has been open 6 months with no activity. Please comment or label `not-stale`, or this will be closed in 14 days.'
|
|
||||||
close-issue-message: 'This issue was automatically closed due to no activity for 6 months plus the 14 day notice period.'
|
|
||||||
days-before-issue-stale: 182 # 6 months
|
|
||||||
days-before-issue-close: 14 # 2 weeks
|
|
||||||
exempt-issue-labels: not-stale
|
|
||||||
|
|
||||||
stale-pr-message: 'This pull request is stale because it has been open 6 months with no activity. Please comment or label `not-stale`, or this will be closed in 14 days.'
|
|
||||||
close-pr-message: 'This pull request was automatically closed due to no activity for 6 months plus the 14 day notice period.'
|
|
||||||
days-before-pr-stale: 182 # 6 months
|
|
||||||
days-before-pr-close: 14 # 2 week
|
|
||||||
exempt-pr-labels: not-stale
|
|
||||||
exempt-draft-pr: false
|
|
||||||
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
*_wire.txt
|
|
||||||
*_wire.bin
|
|
||||||
.DS_Store
|
|
||||||
**/.build
|
|
||||||
build
|
|
||||||
**/Packages
|
|
||||||
/*.xcodeproj
|
|
||||||
**/xcuserdata/
|
|
||||||
**/xcshareddata/
|
|
||||||
**/.swiftpm/
|
|
||||||
*.o
|
|
||||||
*.o.d
|
|
||||||
*.class
|
|
||||||
*.a
|
|
||||||
*.swp
|
|
||||||
*~
|
|
||||||
*.vcxproj
|
|
||||||
*.vcxproj.filters
|
|
||||||
*.vcxproj.user
|
|
||||||
*.sln
|
|
||||||
*.suo
|
|
||||||
*.opendb
|
|
||||||
*.keystore
|
|
||||||
**/.vs/**
|
|
||||||
**/bin/**
|
|
||||||
!tests/rust_usage_test/bin/**
|
|
||||||
**/gen/**
|
|
||||||
**/libs/**
|
|
||||||
**/obj/**
|
|
||||||
**/*.dir/**
|
|
||||||
**/CMakeFiles/**
|
|
||||||
**/cmake_install.cmake
|
|
||||||
**/install_manifest.txt
|
|
||||||
**/CMakeCache.txt
|
|
||||||
**/CMakeTestfile.cmake
|
|
||||||
**/CPackConfig.cmake
|
|
||||||
**/CPackSourceConfig.cmake
|
|
||||||
**/compile_commands.json
|
|
||||||
**/Debug/**
|
|
||||||
**/Release/**
|
|
||||||
**/RelWithDebInfo/**
|
|
||||||
**/x64/ #build artifacts from VS
|
|
||||||
build.xml
|
|
||||||
local.properties
|
|
||||||
project.properties
|
|
||||||
proguard-project.txt
|
|
||||||
linklint_results
|
|
||||||
Makefile
|
|
||||||
flatbenchmark
|
|
||||||
flatbenchmark.exe
|
|
||||||
flatc
|
|
||||||
flatc.exe
|
|
||||||
flathash
|
|
||||||
flathash.exe
|
|
||||||
flattests
|
|
||||||
flattests.exe
|
|
||||||
flattests_cpp17
|
|
||||||
flattests_cpp17.exe
|
|
||||||
flatsamplebinary
|
|
||||||
flatsamplebinary.exe
|
|
||||||
flatsampletext
|
|
||||||
flatsampletext.exe
|
|
||||||
flatsamplebfbs
|
|
||||||
flatsamplebfbs.exe
|
|
||||||
grpctest
|
|
||||||
grpctest.exe
|
|
||||||
snapshot.sh
|
|
||||||
tags
|
|
||||||
tests/dart_gen
|
|
||||||
tests/go_gen
|
|
||||||
tests/monsterdata_java_wire.mon
|
|
||||||
tests/monsterdata_java_wire_sp.mon
|
|
||||||
tests/monsterdata_go_wire.mon
|
|
||||||
tests/monsterdata_javascript_wire.mon
|
|
||||||
tests/monsterdata_lobster_wire.mon
|
|
||||||
tests/monsterdata_rust_wire.mon
|
|
||||||
tests/php/
|
|
||||||
CMakeLists.txt.user
|
|
||||||
CMakeScripts/**
|
|
||||||
CTestTestfile.cmake
|
|
||||||
flatbuffers-config-version.cmake
|
|
||||||
FlatBuffers.cbp
|
|
||||||
build/Xcode/FlatBuffers.xcodeproj/project.xcworkspace/**
|
|
||||||
build/Xcode/FlatBuffers.xcodeproj/xcuserdata/**
|
|
||||||
FlatBuffers.xcodeproj/
|
|
||||||
java/.idea
|
|
||||||
java/*.iml
|
|
||||||
.idea
|
|
||||||
*.iml
|
|
||||||
target
|
|
||||||
java/target
|
|
||||||
**/*.pyc
|
|
||||||
build/VS2010/FlatBuffers.sdf
|
|
||||||
build/VS2010/FlatBuffers.opensdf
|
|
||||||
build/VS2010/ipch/**/*.ipch
|
|
||||||
*.so
|
|
||||||
Testing/Temporary
|
|
||||||
.cproject
|
|
||||||
.settings/
|
|
||||||
.project
|
|
||||||
net/**/obj
|
|
||||||
node_modules/
|
|
||||||
android/.externalNativeBuild/
|
|
||||||
android/.gradle/
|
|
||||||
android/build/
|
|
||||||
samples/android/.externalNativeBuild/
|
|
||||||
samples/android/.gradle/
|
|
||||||
samples/android/build/
|
|
||||||
js/**/*.js
|
|
||||||
js/**/*.d.ts
|
|
||||||
mjs/**/*.js
|
|
||||||
mjs/**/*.d.ts
|
|
||||||
/bazel-bin
|
|
||||||
/bazel-flatbuffers
|
|
||||||
/bazel-genfiles
|
|
||||||
/bazel-out
|
|
||||||
/bazel-testlogs
|
|
||||||
.ninja_deps
|
|
||||||
.ninja_log
|
|
||||||
build.ninja
|
|
||||||
rules.ninja
|
|
||||||
.vscode
|
|
||||||
dart/.pub/
|
|
||||||
dart/.packages
|
|
||||||
dart/pubspec.lock
|
|
||||||
dart/.dart_tool/
|
|
||||||
dart/build/
|
|
||||||
dart/doc/api/
|
|
||||||
Cargo.lock
|
|
||||||
.corpus**
|
|
||||||
.seed**
|
|
||||||
.crash**
|
|
||||||
grpc/google/
|
|
||||||
**/Package.resolved
|
|
||||||
.clangd/**
|
|
||||||
package-lock.json
|
|
||||||
/*.ilk
|
|
||||||
/*.pdb
|
|
||||||
.clwb
|
|
||||||
yarn-error.log
|
|
||||||
.cache/
|
|
||||||
/flatbuffers.lib
|
|
||||||
.cmake/
|
|
||||||
**/dist
|
|
||||||
**/vendor
|
|
||||||
**/go.sum
|
|
||||||
flatbuffers.pc
|
|
||||||
**/FlatBuffers.Test.Swift.xcodeproj
|
|
||||||
**/html/**
|
|
||||||
**/latex/**
|
|
||||||
# https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_BASE_DIR
|
|
||||||
cmake-build-debug/
|
|
||||||
_deps/
|
|
||||||
**/.gradle/**
|
|
||||||
kotlin/**/generated
|
|
||||||
MODULE.bazel.lock
|
|
||||||
|
|
||||||
# Ignore the generated docs
|
|
||||||
docs/site
|
|
||||||
|
|
||||||
# Ignore generated files
|
|
||||||
*.fbs.h
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
hoist=false
|
|
||||||
-202
@@ -1,202 +0,0 @@
|
|||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
|
||||||
|
|
||||||
package(
|
|
||||||
default_visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "distribution",
|
|
||||||
srcs = [
|
|
||||||
"BUILD.bazel",
|
|
||||||
] + glob([
|
|
||||||
"*.cc",
|
|
||||||
"*.h",
|
|
||||||
]),
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "namer",
|
|
||||||
hdrs = [
|
|
||||||
"idl_namer.h",
|
|
||||||
"namer.h",
|
|
||||||
],
|
|
||||||
strip_include_prefix = "/include",
|
|
||||||
visibility = ["//:__subpackages__"],
|
|
||||||
deps = ["//:runtime_cc"],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "python",
|
|
||||||
srcs = ["python.cc"],
|
|
||||||
hdrs = ["python.h"],
|
|
||||||
strip_include_prefix = "/include",
|
|
||||||
visibility = [
|
|
||||||
"//grpc:__subpackages__",
|
|
||||||
"//src:__subpackages__",
|
|
||||||
],
|
|
||||||
deps = [":namer"],
|
|
||||||
)
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
#ifndef FLATBUFFERS_INCLUDE_CODEGEN_IDL_NAMER_H_
|
|
||||||
#define FLATBUFFERS_INCLUDE_CODEGEN_IDL_NAMER_H_
|
|
||||||
|
|
||||||
#include "codegen/namer.h"
|
|
||||||
#include "flatbuffers/idl.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Provides Namer capabilities to types defined in the flatbuffers IDL.
|
|
||||||
class IdlNamer : public Namer {
|
|
||||||
public:
|
|
||||||
explicit IdlNamer(Config config, std::set<std::string> keywords)
|
|
||||||
: Namer(config, std::move(keywords)) {}
|
|
||||||
|
|
||||||
using Namer::Constant;
|
|
||||||
using Namer::Directories;
|
|
||||||
using Namer::Field;
|
|
||||||
using Namer::File;
|
|
||||||
using Namer::Function;
|
|
||||||
using Namer::Method;
|
|
||||||
using Namer::Namespace;
|
|
||||||
using Namer::NamespacedType;
|
|
||||||
using Namer::ObjectType;
|
|
||||||
using Namer::Type;
|
|
||||||
using Namer::Variable;
|
|
||||||
using Namer::Variant;
|
|
||||||
|
|
||||||
std::string Constant(const FieldDef& d) const { return Constant(d.name); }
|
|
||||||
|
|
||||||
// Types are always structs or enums so we can only expose these two
|
|
||||||
// overloads.
|
|
||||||
std::string Type(const StructDef& d) const { return Type(d.name); }
|
|
||||||
std::string Type(const EnumDef& d) const { return Type(d.name); }
|
|
||||||
|
|
||||||
std::string Function(const Definition& s) const { return Function(s.name); }
|
|
||||||
std::string Function(const std::string& prefix, const Definition& s) const {
|
|
||||||
return Function(prefix + s.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Field(const FieldDef& s) const { return Field(s.name); }
|
|
||||||
std::string Field(const FieldDef& d, const std::string& s) const {
|
|
||||||
return Field(d.name + "_" + s);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Variable(const FieldDef& s) const { return Variable(s.name); }
|
|
||||||
|
|
||||||
std::string Variable(const StructDef& s) const { return Variable(s.name); }
|
|
||||||
|
|
||||||
std::string Variant(const EnumVal& s) const { return Variant(s.name); }
|
|
||||||
|
|
||||||
std::string EnumVariant(const EnumDef& e, const EnumVal& v) const {
|
|
||||||
return Type(e) + config_.enum_variant_seperator + Variant(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ObjectType(const StructDef& d) const {
|
|
||||||
return ObjectType(d.name);
|
|
||||||
}
|
|
||||||
std::string ObjectType(const EnumDef& d) const { return ObjectType(d.name); }
|
|
||||||
|
|
||||||
std::string Method(const FieldDef& d, const std::string& suffix) const {
|
|
||||||
return Method(d.name, suffix);
|
|
||||||
}
|
|
||||||
std::string Method(const std::string& prefix, const StructDef& d) const {
|
|
||||||
return Method(prefix, d.name);
|
|
||||||
}
|
|
||||||
std::string Method(const std::string& prefix, const FieldDef& d) const {
|
|
||||||
return Method(prefix, d.name);
|
|
||||||
}
|
|
||||||
std::string Method(const std::string& prefix, const FieldDef& d,
|
|
||||||
const std::string& suffix) const {
|
|
||||||
return Method(prefix, d.name, suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Namespace(const struct Namespace& ns) const {
|
|
||||||
return Namespace(ns.components);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NamespacedEnumVariant(const EnumDef& e, const EnumVal& v) const {
|
|
||||||
return NamespacedString(e.defined_namespace, EnumVariant(e, v));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NamespacedType(const Definition& def) const {
|
|
||||||
return NamespacedString(def.defined_namespace, Type(def.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NamespacedObjectType(const Definition& def) const {
|
|
||||||
return NamespacedString(def.defined_namespace, ObjectType(def.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Directories(const struct Namespace& ns,
|
|
||||||
SkipDir skips = SkipDir::None,
|
|
||||||
Case input_case = Case::kUpperCamel) const {
|
|
||||||
return Directories(ns.components, skips, input_case);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Legacy fields do not really follow the usual config and should be
|
|
||||||
// considered for deprecation.
|
|
||||||
|
|
||||||
std::string LegacyRustNativeVariant(const EnumVal& v) const {
|
|
||||||
return ConvertCase(EscapeKeyword(v.name), Case::kUpperCamel);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LegacyRustFieldOffsetName(const FieldDef& field) const {
|
|
||||||
return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper);
|
|
||||||
}
|
|
||||||
std::string LegacyRustUnionTypeOffsetName(const FieldDef& field) const {
|
|
||||||
return "VT_" +
|
|
||||||
ConvertCase(EscapeKeyword(field.name + "_type"), Case::kAllUpper);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LegacySwiftVariant(const EnumVal& ev) const {
|
|
||||||
auto name = ev.name;
|
|
||||||
if (isupper(name.front())) {
|
|
||||||
std::transform(name.begin(), name.end(), name.begin(), CharToLower);
|
|
||||||
}
|
|
||||||
return EscapeKeyword(ConvertCase(name, Case::kLowerCamel));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Also used by Kotlin, lol.
|
|
||||||
std::string LegacyJavaMethod2(const std::string& prefix, const StructDef& sd,
|
|
||||||
const std::string& suffix) const {
|
|
||||||
return prefix + sd.name + suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LegacyKotlinVariant(EnumVal& ev) const {
|
|
||||||
// Namer assumes the input case is snake case which is wrong...
|
|
||||||
return ConvertCase(EscapeKeyword(ev.name), Case::kLowerCamel);
|
|
||||||
}
|
|
||||||
// Kotlin methods escapes keywords after case conversion but before
|
|
||||||
// prefixing and suffixing.
|
|
||||||
std::string LegacyKotlinMethod(const std::string& prefix, const FieldDef& d,
|
|
||||||
const std::string& suffix) const {
|
|
||||||
return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) +
|
|
||||||
suffix;
|
|
||||||
}
|
|
||||||
std::string LegacyKotlinMethod(const std::string& prefix, const StructDef& d,
|
|
||||||
const std::string& suffix) const {
|
|
||||||
return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) +
|
|
||||||
suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a mix of snake case and keep casing, when Ts should be using
|
|
||||||
// lower camel case.
|
|
||||||
std::string LegacyTsMutateMethod(const FieldDef& d) {
|
|
||||||
return "mutate_" + d.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LegacyRustUnionTypeMethod(const FieldDef& d) {
|
|
||||||
// assert d is a union
|
|
||||||
// d should convert case but not escape keywords due to historical reasons
|
|
||||||
return ConvertCase(d.name, config_.fields, Case::kLowerCamel) + "_type";
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string NamespacedString(const struct Namespace* ns,
|
|
||||||
const std::string& str) const {
|
|
||||||
std::string ret;
|
|
||||||
if (ns != nullptr) {
|
|
||||||
ret += Namespace(ns->components);
|
|
||||||
}
|
|
||||||
if (!ret.empty()) ret += config_.namespace_seperator;
|
|
||||||
return ret + str;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is a temporary helper function for code generators to call until all
|
|
||||||
// flag-overriding logic into flatc.cpp
|
|
||||||
inline Namer::Config WithFlagOptions(const Namer::Config& input,
|
|
||||||
const IDLOptions& opts,
|
|
||||||
const std::string& path) {
|
|
||||||
Namer::Config result = input;
|
|
||||||
result.object_prefix = opts.object_prefix;
|
|
||||||
result.object_suffix = opts.object_suffix;
|
|
||||||
result.output_path = path;
|
|
||||||
result.filename_suffix = opts.filename_suffix;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_INCLUDE_CODEGEN_IDL_NAMER_H_
|
|
||||||
@@ -1,286 +0,0 @@
|
|||||||
#ifndef FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_
|
|
||||||
#define FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/util.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Options for Namer::File.
|
|
||||||
enum class SkipFile {
|
|
||||||
None = 0,
|
|
||||||
Suffix = 1,
|
|
||||||
Extension = 2,
|
|
||||||
SuffixAndExtension = 3,
|
|
||||||
};
|
|
||||||
inline SkipFile operator&(SkipFile a, SkipFile b) {
|
|
||||||
return static_cast<SkipFile>(static_cast<int>(a) & static_cast<int>(b));
|
|
||||||
}
|
|
||||||
// Options for Namer::Directories
|
|
||||||
enum class SkipDir {
|
|
||||||
None = 0,
|
|
||||||
// Skip prefixing the -o $output_path.
|
|
||||||
OutputPath = 1,
|
|
||||||
// Skip trailing path seperator.
|
|
||||||
TrailingPathSeperator = 2,
|
|
||||||
OutputPathAndTrailingPathSeparator = 3,
|
|
||||||
};
|
|
||||||
inline SkipDir operator&(SkipDir a, SkipDir b) {
|
|
||||||
return static_cast<SkipDir>(static_cast<int>(a) & static_cast<int>(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
// `Namer` applies style configuration to symbols in generated code. It manages
|
|
||||||
// casing, escapes keywords, and object API naming.
|
|
||||||
// TODO: Refactor all code generators to use this.
|
|
||||||
class Namer {
|
|
||||||
public:
|
|
||||||
struct Config {
|
|
||||||
// Symbols in code.
|
|
||||||
|
|
||||||
// Case style for flatbuffers-defined types.
|
|
||||||
// e.g. `class TableA {}`
|
|
||||||
Case types;
|
|
||||||
// Case style for flatbuffers-defined constants.
|
|
||||||
// e.g. `uint64_t ENUM_A_MAX`;
|
|
||||||
Case constants;
|
|
||||||
// Case style for flatbuffers-defined methods.
|
|
||||||
// e.g. `class TableA { int field_a(); }`
|
|
||||||
Case methods;
|
|
||||||
// Case style for flatbuffers-defined functions.
|
|
||||||
// e.g. `TableA* get_table_a_root()`;
|
|
||||||
Case functions;
|
|
||||||
// Case style for flatbuffers-defined fields.
|
|
||||||
// e.g. `struct Struct { int my_field; }`
|
|
||||||
Case fields;
|
|
||||||
// Case style for flatbuffers-defined variables.
|
|
||||||
// e.g. `int my_variable = 2`
|
|
||||||
Case variables;
|
|
||||||
// Case style for flatbuffers-defined variants.
|
|
||||||
// e.g. `enum class Enum { MyVariant, }`
|
|
||||||
Case variants;
|
|
||||||
// Seperator for qualified enum names.
|
|
||||||
// e.g. `Enum::MyVariant` uses `::`.
|
|
||||||
std::string enum_variant_seperator;
|
|
||||||
|
|
||||||
// Configures, when formatting code, whether symbols are checked against
|
|
||||||
// keywords and escaped before or after case conversion. It does not make
|
|
||||||
// sense to do so before, but its legacy behavior. :shrug:
|
|
||||||
// TODO(caspern): Deprecate.
|
|
||||||
enum class Escape {
|
|
||||||
BeforeConvertingCase,
|
|
||||||
AfterConvertingCase,
|
|
||||||
};
|
|
||||||
Escape escape_keywords;
|
|
||||||
|
|
||||||
// Namespaces
|
|
||||||
|
|
||||||
// e.g. `namespace my_namespace {}`
|
|
||||||
Case namespaces;
|
|
||||||
// The seperator between namespaces in a namespace path.
|
|
||||||
std::string namespace_seperator;
|
|
||||||
|
|
||||||
// Object API.
|
|
||||||
// Native versions flatbuffers types have this prefix.
|
|
||||||
// e.g. "" (it's usually empty string)
|
|
||||||
std::string object_prefix;
|
|
||||||
// Native versions flatbuffers types have this suffix.
|
|
||||||
// e.g. "T"
|
|
||||||
std::string object_suffix;
|
|
||||||
|
|
||||||
// Keywords.
|
|
||||||
// Prefix used to escape keywords. It is usually empty string.
|
|
||||||
std::string keyword_prefix;
|
|
||||||
// Suffix used to escape keywords. It is usually "_".
|
|
||||||
std::string keyword_suffix;
|
|
||||||
// The casing used for keywords when escaping. For most languages, keywords
|
|
||||||
// are case sensitive. PHP is an instance where some keywords are case
|
|
||||||
// insensitive.
|
|
||||||
enum class KeywordsCasing {
|
|
||||||
CaseSensitive,
|
|
||||||
CaseInsensitive,
|
|
||||||
};
|
|
||||||
KeywordsCasing keywords_casing;
|
|
||||||
|
|
||||||
// Files.
|
|
||||||
|
|
||||||
// Case style for filenames. e.g. `foo_bar_generated.rs`
|
|
||||||
Case filenames;
|
|
||||||
// Case style for directories, e.g. `output_files/foo_bar/baz/`
|
|
||||||
Case directories;
|
|
||||||
// The directory within which we will generate files.
|
|
||||||
std::string output_path;
|
|
||||||
// Suffix for generated file names, e.g. "_generated".
|
|
||||||
std::string filename_suffix;
|
|
||||||
// Extension for generated files, e.g. ".cpp" or ".rs".
|
|
||||||
std::string filename_extension;
|
|
||||||
};
|
|
||||||
Namer(Config config, std::set<std::string> keywords)
|
|
||||||
: config_(config), keywords_(std::move(keywords)) {}
|
|
||||||
|
|
||||||
virtual ~Namer() {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::string Method(const T& s) const {
|
|
||||||
return Method(s.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Method(const std::string& pre, const std::string& mid,
|
|
||||||
const std::string& suf) const {
|
|
||||||
return Format(pre + "_" + mid + "_" + suf, config_.methods);
|
|
||||||
}
|
|
||||||
virtual std::string Method(const std::string& pre,
|
|
||||||
const std::string& suf) const {
|
|
||||||
return Format(pre + "_" + suf, config_.methods);
|
|
||||||
}
|
|
||||||
virtual std::string Method(const std::string& s) const {
|
|
||||||
return Format(s, config_.methods);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Constant(const std::string& s) const {
|
|
||||||
return Format(s, config_.constants);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Function(const std::string& s) const {
|
|
||||||
return Format(s, config_.functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Variable(const std::string& s) const {
|
|
||||||
return Format(s, config_.variables);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::string Variable(const std::string& p, const T& s) const {
|
|
||||||
return Format(p + "_" + s.name, config_.variables);
|
|
||||||
}
|
|
||||||
virtual std::string Variable(const std::string& p,
|
|
||||||
const std::string& s) const {
|
|
||||||
return Format(p + "_" + s, config_.variables);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Namespace(const std::string& s) const {
|
|
||||||
return Format(s, config_.namespaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Namespace(const std::vector<std::string>& ns) const {
|
|
||||||
std::string result;
|
|
||||||
for (auto it = ns.begin(); it != ns.end(); it++) {
|
|
||||||
if (it != ns.begin()) result += config_.namespace_seperator;
|
|
||||||
result += Namespace(*it);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string NamespacedType(const std::vector<std::string>& ns,
|
|
||||||
const std::string& s) const {
|
|
||||||
return (ns.empty() ? "" : (Namespace(ns) + config_.namespace_seperator)) +
|
|
||||||
Type(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns `filename` with the right casing, suffix, and extension.
|
|
||||||
virtual std::string File(const std::string& filename,
|
|
||||||
SkipFile skips = SkipFile::None) const {
|
|
||||||
const bool skip_suffix = (skips & SkipFile::Suffix) != SkipFile::None;
|
|
||||||
const bool skip_ext = (skips & SkipFile::Extension) != SkipFile::None;
|
|
||||||
return ConvertCase(filename, config_.filenames, Case::kUpperCamel) +
|
|
||||||
(skip_suffix ? "" : config_.filename_suffix) +
|
|
||||||
(skip_ext ? "" : config_.filename_extension);
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
std::string File(const T& f, SkipFile skips = SkipFile::None) const {
|
|
||||||
return File(f.name, skips);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Formats `directories` prefixed with the output_path and joined with the
|
|
||||||
// right seperator. Output path prefixing and the trailing separator may be
|
|
||||||
// skiped using `skips`.
|
|
||||||
// Callers may want to use `EnsureDirExists` with the result.
|
|
||||||
// input_case is used to tell how to modify namespace. e.g. kUpperCamel will
|
|
||||||
// add a underscode between case changes, so MyGame turns into My_Game
|
|
||||||
// (depending also on the output_case).
|
|
||||||
virtual std::string Directories(const std::vector<std::string>& directories,
|
|
||||||
SkipDir skips = SkipDir::None,
|
|
||||||
Case input_case = Case::kUpperCamel) const {
|
|
||||||
const bool skip_output_path =
|
|
||||||
(skips & SkipDir::OutputPath) != SkipDir::None;
|
|
||||||
const bool skip_trailing_seperator =
|
|
||||||
(skips & SkipDir::TrailingPathSeperator) != SkipDir::None;
|
|
||||||
std::string result = skip_output_path ? "" : config_.output_path;
|
|
||||||
for (auto d = directories.begin(); d != directories.end(); d++) {
|
|
||||||
result += ConvertCase(*d, config_.directories, input_case);
|
|
||||||
result.push_back(kPathSeparator);
|
|
||||||
}
|
|
||||||
if (skip_trailing_seperator && !result.empty()) result.pop_back();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string NormalizeKeywordCase(const std::string& name) const {
|
|
||||||
if (config_.keywords_casing == Config::KeywordsCasing::CaseInsensitive) {
|
|
||||||
return ConvertCase(name, Case::kAllLower);
|
|
||||||
} else {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string EscapeKeyword(const std::string& name) const {
|
|
||||||
if (keywords_.find(NormalizeKeywordCase(name)) == keywords_.end()) {
|
|
||||||
return name;
|
|
||||||
} else {
|
|
||||||
return config_.keyword_prefix + name + config_.keyword_suffix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Type(const std::string& s) const {
|
|
||||||
return Format(s, config_.types);
|
|
||||||
}
|
|
||||||
virtual std::string Type(const std::string& t, const std::string& s) const {
|
|
||||||
return Format(t + "_" + s, config_.types);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string ObjectType(const std::string& s) const {
|
|
||||||
return config_.object_prefix + Type(s) + config_.object_suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Field(const std::string& s) const {
|
|
||||||
return Format(s, config_.fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Variant(const std::string& s) const {
|
|
||||||
return Format(s, config_.variants);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::string Format(const std::string& s, Case casing) const {
|
|
||||||
if (config_.escape_keywords == Config::Escape::BeforeConvertingCase) {
|
|
||||||
return ConvertCase(EscapeKeyword(s), casing, Case::kLowerCamel);
|
|
||||||
} else {
|
|
||||||
return EscapeKeyword(ConvertCase(s, casing, Case::kLowerCamel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Denamespaces a string (e.g. The.Quick.Brown.Fox) by returning the last part
|
|
||||||
// after the `delimiter` (Fox) and placing the rest in `namespace_prefix`
|
|
||||||
// (The.Quick.Brown).
|
|
||||||
virtual std::string Denamespace(const std::string& s,
|
|
||||||
std::string& namespace_prefix,
|
|
||||||
const char delimiter = '.') const {
|
|
||||||
const size_t pos = s.find_last_of(delimiter);
|
|
||||||
if (pos == std::string::npos) {
|
|
||||||
namespace_prefix = "";
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
namespace_prefix = s.substr(0, pos);
|
|
||||||
return s.substr(pos + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same as above, but disregards the prefix.
|
|
||||||
virtual std::string Denamespace(const std::string& s,
|
|
||||||
const char delimiter = '.') const {
|
|
||||||
std::string prefix;
|
|
||||||
return Denamespace(s, prefix, delimiter);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Config config_;
|
|
||||||
const std::set<std::string> keywords_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#include "codegen/python.h"
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
namespace python {
|
|
||||||
Version::Version(const std::string& version) {
|
|
||||||
std::stringstream ss(version);
|
|
||||||
char dot;
|
|
||||||
ss >> major >> dot >> minor >> dot >> micro;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Version::IsValid() const {
|
|
||||||
return (major == 0 || major == 2 || major == 3) && minor >= 0 && micro >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<std::string> Keywords(const Version& version) {
|
|
||||||
switch (version.major) {
|
|
||||||
case 2:
|
|
||||||
// https://docs.python.org/2/reference/lexical_analysis.html#keywords
|
|
||||||
return {
|
|
||||||
"and", "as", "assert", "break", "class", "continue", "def",
|
|
||||||
"del", "elif", "else", "except", "exec", "finally", "for",
|
|
||||||
"from", "global", "if", "import", "in", "is", "lambda",
|
|
||||||
"not", "or", "pass", "print", "raise", "return", "try",
|
|
||||||
"while", "with", "yield",
|
|
||||||
};
|
|
||||||
case 0:
|
|
||||||
case 3:
|
|
||||||
// https://docs.python.org/3/reference/lexical_analysis.html#keywords
|
|
||||||
return {
|
|
||||||
"and", "as", "assert", "async", "await", "break",
|
|
||||||
"class", "continue", "def", "del", "elif", "else",
|
|
||||||
"except", "False", "finally", "for", "from", "global",
|
|
||||||
"if", "import", "in", "is", "lambda", "None",
|
|
||||||
"nonlocal", "not", "or", "pass", "raise", "return",
|
|
||||||
"True", "try", "while", "with", "yield",
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const python::Import& python::Imports::Import(const std::string& module) {
|
|
||||||
python::Import import;
|
|
||||||
import.module = module;
|
|
||||||
imports.push_back(std::move(import));
|
|
||||||
return imports.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
const python::Import& python::Imports::Import(const std::string& module,
|
|
||||||
const std::string& name) {
|
|
||||||
python::Import import;
|
|
||||||
import.module = module;
|
|
||||||
import.name = name;
|
|
||||||
imports.push_back(std::move(import));
|
|
||||||
return imports.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
const python::Import& python::Imports::Export(const std::string& module) {
|
|
||||||
python::Import import;
|
|
||||||
import.module = module;
|
|
||||||
exports.push_back(std::move(import));
|
|
||||||
return exports.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
const python::Import& python::Imports::Export(const std::string& module,
|
|
||||||
const std::string& name) {
|
|
||||||
python::Import import;
|
|
||||||
import.module = module;
|
|
||||||
import.name = name;
|
|
||||||
exports.push_back(std::move(import));
|
|
||||||
return exports.back();
|
|
||||||
}
|
|
||||||
} // namespace python
|
|
||||||
} // namespace flatbuffers
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
#ifndef FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_
|
|
||||||
#define FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "codegen/namer.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
namespace python {
|
|
||||||
static const Namer::Config kConfig = {
|
|
||||||
/*types=*/Case::kKeep,
|
|
||||||
/*constants=*/Case::kScreamingSnake,
|
|
||||||
/*methods=*/Case::kUpperCamel,
|
|
||||||
/*functions=*/Case::kUpperCamel,
|
|
||||||
/*fields=*/Case::kLowerCamel,
|
|
||||||
/*variable=*/Case::kLowerCamel,
|
|
||||||
/*variants=*/Case::kKeep,
|
|
||||||
/*enum_variant_seperator=*/".",
|
|
||||||
/*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
|
|
||||||
/*namespaces=*/Case::kKeep, // Packages in python.
|
|
||||||
/*namespace_seperator=*/".",
|
|
||||||
/*object_prefix=*/"",
|
|
||||||
/*object_suffix=*/"T",
|
|
||||||
/*keyword_prefix=*/"",
|
|
||||||
/*keyword_suffix=*/"_",
|
|
||||||
/*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive,
|
|
||||||
/*filenames=*/Case::kKeep,
|
|
||||||
/*directories=*/Case::kKeep,
|
|
||||||
/*output_path=*/"",
|
|
||||||
/*filename_suffix=*/"",
|
|
||||||
/*filename_extension=*/".py",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const Namer::Config kStubConfig = {
|
|
||||||
/*types=*/Case::kKeep,
|
|
||||||
/*constants=*/Case::kScreamingSnake,
|
|
||||||
/*methods=*/Case::kUpperCamel,
|
|
||||||
/*functions=*/Case::kUpperCamel,
|
|
||||||
/*fields=*/Case::kLowerCamel,
|
|
||||||
/*variables=*/Case::kLowerCamel,
|
|
||||||
/*variants=*/Case::kKeep,
|
|
||||||
/*enum_variant_seperator=*/".",
|
|
||||||
/*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
|
|
||||||
/*namespaces=*/Case::kKeep, // Packages in python.
|
|
||||||
/*namespace_seperator=*/".",
|
|
||||||
/*object_prefix=*/"",
|
|
||||||
/*object_suffix=*/"T",
|
|
||||||
/*keyword_prefix=*/"",
|
|
||||||
/*keyword_suffix=*/"_",
|
|
||||||
/*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive,
|
|
||||||
/*filenames=*/Case::kKeep,
|
|
||||||
/*directories=*/Case::kKeep,
|
|
||||||
/*output_path=*/"",
|
|
||||||
/*filename_suffix=*/"",
|
|
||||||
/*filename_extension=*/".pyi",
|
|
||||||
};
|
|
||||||
|
|
||||||
// `Version` represent a Python version.
|
|
||||||
//
|
|
||||||
// The zero value (i.e. `Version{}`) represents both Python2 and Python3.
|
|
||||||
//
|
|
||||||
// https://docs.python.org/3/faq/general.html#how-does-the-python-version-numbering-scheme-work
|
|
||||||
struct Version {
|
|
||||||
explicit Version(const std::string& version);
|
|
||||||
|
|
||||||
bool IsValid() const;
|
|
||||||
|
|
||||||
int16_t major = 0;
|
|
||||||
int16_t minor = 0;
|
|
||||||
int16_t micro = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::set<std::string> Keywords(const Version& version);
|
|
||||||
|
|
||||||
struct Import {
|
|
||||||
bool IsLocal() const { return module == "."; }
|
|
||||||
|
|
||||||
std::string module;
|
|
||||||
std::string name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Imports {
|
|
||||||
const python::Import& Import(const std::string& module);
|
|
||||||
const python::Import& Import(const std::string& module,
|
|
||||||
const std::string& name);
|
|
||||||
|
|
||||||
const python::Import& Export(const std::string& module);
|
|
||||||
const python::Import& Export(const std::string& module,
|
|
||||||
const std::string& name);
|
|
||||||
|
|
||||||
std::vector<python::Import> imports;
|
|
||||||
std::vector<python::Import> exports;
|
|
||||||
};
|
|
||||||
} // namespace python
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_ALLOCATOR_H_
|
|
||||||
#define FLATBUFFERS_ALLOCATOR_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Allocator interface. This is flatbuffers-specific and meant only for
|
|
||||||
// `vector_downward` usage.
|
|
||||||
class Allocator {
|
|
||||||
public:
|
|
||||||
virtual ~Allocator() {}
|
|
||||||
|
|
||||||
// Allocate `size` bytes of memory.
|
|
||||||
virtual uint8_t* allocate(size_t size) = 0;
|
|
||||||
|
|
||||||
// Deallocate `size` bytes of memory at `p` allocated by this allocator.
|
|
||||||
virtual void deallocate(uint8_t* p, size_t size) = 0;
|
|
||||||
|
|
||||||
// Reallocate `new_size` bytes of memory, replacing the old region of size
|
|
||||||
// `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
|
|
||||||
// and is intended specifcally for `vector_downward` use.
|
|
||||||
// `in_use_back` and `in_use_front` indicate how much of `old_size` is
|
|
||||||
// actually in use at each end, and needs to be copied.
|
|
||||||
virtual uint8_t* reallocate_downward(uint8_t* old_p, size_t old_size,
|
|
||||||
size_t new_size, size_t in_use_back,
|
|
||||||
size_t in_use_front) {
|
|
||||||
FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows
|
|
||||||
uint8_t* new_p = allocate(new_size);
|
|
||||||
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
|
|
||||||
in_use_front);
|
|
||||||
deallocate(old_p, old_size);
|
|
||||||
return new_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
|
|
||||||
// to `new_p` of `new_size`. Only memory of size `in_use_front` and
|
|
||||||
// `in_use_back` will be copied from the front and back of the old memory
|
|
||||||
// allocation.
|
|
||||||
void memcpy_downward(uint8_t* old_p, size_t old_size, uint8_t* new_p,
|
|
||||||
size_t new_size, size_t in_use_back,
|
|
||||||
size_t in_use_front) {
|
|
||||||
memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
|
|
||||||
in_use_back);
|
|
||||||
memcpy(new_p, old_p, in_use_front);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_ALLOCATOR_H_
|
|
||||||
@@ -1,258 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_ARRAY_H_
|
|
||||||
#define FLATBUFFERS_ARRAY_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/stl_emulation.h"
|
|
||||||
#include "flatbuffers/vector.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// This is used as a helper type for accessing arrays.
|
|
||||||
template <typename T, uint16_t length>
|
|
||||||
class Array {
|
|
||||||
// Array<T> can carry only POD data types (scalars or structs).
|
|
||||||
typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
|
|
||||||
scalar_tag;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef uint16_t size_type;
|
|
||||||
typedef typename IndirectHelper<T>::return_type return_type;
|
|
||||||
typedef VectorConstIterator<T, return_type, uoffset_t> const_iterator;
|
|
||||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
|
||||||
|
|
||||||
// If T is a non-pointer and a LE-scalar or a struct (!scalar_tag::value).
|
|
||||||
static FLATBUFFERS_CONSTEXPR bool is_span_observable =
|
|
||||||
!std::is_pointer<T>::value &&
|
|
||||||
((scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1)) ||
|
|
||||||
!scalar_tag::value);
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
|
|
||||||
|
|
||||||
return_type Get(uoffset_t i) const {
|
|
||||||
FLATBUFFERS_ASSERT(i < size());
|
|
||||||
return IndirectHelper<T>::Read(Data(), i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return_type operator[](uoffset_t i) const { return Get(i); }
|
|
||||||
|
|
||||||
// If this is a Vector of enums, T will be its storage type, not the enum
|
|
||||||
// type. This function makes it convenient to retrieve value with enum
|
|
||||||
// type E.
|
|
||||||
template <typename E>
|
|
||||||
E GetEnum(uoffset_t i) const {
|
|
||||||
return static_cast<E>(Get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator begin() const { return const_iterator(Data(), 0); }
|
|
||||||
const_iterator end() const { return const_iterator(Data(), size()); }
|
|
||||||
|
|
||||||
const_reverse_iterator rbegin() const {
|
|
||||||
return const_reverse_iterator(end());
|
|
||||||
}
|
|
||||||
const_reverse_iterator rend() const {
|
|
||||||
return const_reverse_iterator(begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator cbegin() const { return begin(); }
|
|
||||||
const_iterator cend() const { return end(); }
|
|
||||||
|
|
||||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
|
||||||
const_reverse_iterator crend() const { return rend(); }
|
|
||||||
|
|
||||||
// Get a mutable pointer to elements inside this array.
|
|
||||||
// This method used to mutate arrays of structs followed by a @p Mutate
|
|
||||||
// operation. For primitive types use @p Mutate directly.
|
|
||||||
// @warning Assignments and reads to/from the dereferenced pointer are not
|
|
||||||
// automatically converted to the correct endianness.
|
|
||||||
typename flatbuffers::conditional<scalar_tag::value, void, T*>::type
|
|
||||||
GetMutablePointer(uoffset_t i) const {
|
|
||||||
FLATBUFFERS_ASSERT(i < size());
|
|
||||||
return const_cast<T*>(&data()[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change elements if you have a non-const pointer to this object.
|
|
||||||
void Mutate(uoffset_t i, const T& val) { MutateImpl(scalar_tag(), i, val); }
|
|
||||||
|
|
||||||
// The raw data in little endian format. Use with care.
|
|
||||||
const uint8_t* Data() const { return data_; }
|
|
||||||
|
|
||||||
uint8_t* Data() { return data_; }
|
|
||||||
|
|
||||||
// Similarly, but typed, much like std::vector::data
|
|
||||||
const T* data() const { return reinterpret_cast<const T*>(Data()); }
|
|
||||||
T* data() { return reinterpret_cast<T*>(Data()); }
|
|
||||||
|
|
||||||
// Copy data from a span with endian conversion.
|
|
||||||
// If this Array and the span overlap, the behavior is undefined.
|
|
||||||
void CopyFromSpan(flatbuffers::span<const T, length> src) {
|
|
||||||
const auto p1 = reinterpret_cast<const uint8_t*>(src.data());
|
|
||||||
const auto p2 = Data();
|
|
||||||
FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) &&
|
|
||||||
!(p2 >= p1 && p2 < (p1 + length)));
|
|
||||||
(void)p1;
|
|
||||||
(void)p2;
|
|
||||||
CopyFromSpanImpl(flatbuffers::bool_constant<is_span_observable>(), src);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void MutateImpl(flatbuffers::true_type, uoffset_t i, const T& val) {
|
|
||||||
FLATBUFFERS_ASSERT(i < size());
|
|
||||||
WriteScalar(data() + i, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MutateImpl(flatbuffers::false_type, uoffset_t i, const T& val) {
|
|
||||||
*(GetMutablePointer(i)) = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CopyFromSpanImpl(flatbuffers::true_type,
|
|
||||||
flatbuffers::span<const T, length> src) {
|
|
||||||
// Use std::memcpy() instead of std::copy() to avoid performance degradation
|
|
||||||
// due to aliasing if T is char or unsigned char.
|
|
||||||
// The size is known at compile time, so memcpy would be inlined.
|
|
||||||
std::memcpy(data(), src.data(), length * sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy data from flatbuffers::span with endian conversion.
|
|
||||||
void CopyFromSpanImpl(flatbuffers::false_type,
|
|
||||||
flatbuffers::span<const T, length> src) {
|
|
||||||
for (size_type k = 0; k < length; k++) {
|
|
||||||
Mutate(k, src[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This class is only used to access pre-existing data. Don't ever
|
|
||||||
// try to construct these manually.
|
|
||||||
// 'constexpr' allows us to use 'size()' at compile time.
|
|
||||||
// @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
|
|
||||||
// a constructor.
|
|
||||||
#if defined(__cpp_constexpr)
|
|
||||||
constexpr Array();
|
|
||||||
#else
|
|
||||||
Array();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t data_[length * sizeof(T)];
|
|
||||||
|
|
||||||
private:
|
|
||||||
// This class is a pointer. Copying will therefore create an invalid object.
|
|
||||||
// Private and unimplemented copy constructor.
|
|
||||||
Array(const Array&);
|
|
||||||
Array& operator=(const Array&);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialization for Array[struct] with access using Offset<void> pointer.
|
|
||||||
// This specialization used by idl_gen_text.cpp.
|
|
||||||
template <typename T, uint16_t length, template <typename> class OffsetT>
|
|
||||||
class Array<OffsetT<T>, length> {
|
|
||||||
static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef const void* return_type;
|
|
||||||
typedef uint16_t size_type;
|
|
||||||
|
|
||||||
const uint8_t* Data() const { return data_; }
|
|
||||||
|
|
||||||
// Make idl_gen_text.cpp::PrintContainer happy.
|
|
||||||
return_type operator[](uoffset_t) const {
|
|
||||||
FLATBUFFERS_ASSERT(false);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// This class is only used to access pre-existing data.
|
|
||||||
Array();
|
|
||||||
Array(const Array&);
|
|
||||||
Array& operator=(const Array&);
|
|
||||||
|
|
||||||
uint8_t data_[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class U, uint16_t N>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(Array<U, N>& arr)
|
|
||||||
FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(
|
|
||||||
Array<U, N>::is_span_observable,
|
|
||||||
"wrong type U, only plain struct, LE-scalar, or byte types are allowed");
|
|
||||||
return span<U, N>(arr.data(), N);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U, uint16_t N>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U, N> make_span(
|
|
||||||
const Array<U, N>& arr) FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(
|
|
||||||
Array<U, N>::is_span_observable,
|
|
||||||
"wrong type U, only plain struct, LE-scalar, or byte types are allowed");
|
|
||||||
return span<const U, N>(arr.data(), N);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U, uint16_t N>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t, sizeof(U) * N>
|
|
||||||
make_bytes_span(Array<U, N>& arr) FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(Array<U, N>::is_span_observable,
|
|
||||||
"internal error, Array<T> might hold only scalars or structs");
|
|
||||||
return span<uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U, uint16_t N>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t, sizeof(U) * N>
|
|
||||||
make_bytes_span(const Array<U, N>& arr) FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(Array<U, N>::is_span_observable,
|
|
||||||
"internal error, Array<T> might hold only scalars or structs");
|
|
||||||
return span<const uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cast a raw T[length] to a raw flatbuffers::Array<T, length>
|
|
||||||
// without endian conversion. Use with care.
|
|
||||||
// TODO: move these Cast-methods to `internal` namespace.
|
|
||||||
template <typename T, uint16_t length>
|
|
||||||
Array<T, length>& CastToArray(T (&arr)[length]) {
|
|
||||||
return *reinterpret_cast<Array<T, length>*>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, uint16_t length>
|
|
||||||
const Array<T, length>& CastToArray(const T (&arr)[length]) {
|
|
||||||
return *reinterpret_cast<const Array<T, length>*>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename T, uint16_t length>
|
|
||||||
Array<E, length>& CastToArrayOfEnum(T (&arr)[length]) {
|
|
||||||
static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
|
|
||||||
return *reinterpret_cast<Array<E, length>*>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename T, uint16_t length>
|
|
||||||
const Array<E, length>& CastToArrayOfEnum(const T (&arr)[length]) {
|
|
||||||
static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
|
|
||||||
return *reinterpret_cast<const Array<E, length>*>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, uint16_t length>
|
|
||||||
bool operator==(const Array<T, length>& lhs,
|
|
||||||
const Array<T, length>& rhs) noexcept {
|
|
||||||
return std::addressof(lhs) == std::addressof(rhs) ||
|
|
||||||
(lhs.size() == rhs.size() &&
|
|
||||||
std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_ARRAY_H_
|
|
||||||
@@ -1,503 +0,0 @@
|
|||||||
#ifndef FLATBUFFERS_BASE_H_
|
|
||||||
#define FLATBUFFERS_BASE_H_
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
// If activate should be declared and included first.
|
|
||||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
|
||||||
defined(_MSC_VER) && defined(_DEBUG)
|
|
||||||
// The _CRTDBG_MAP_ALLOC inside <crtdbg.h> will replace
|
|
||||||
// calloc/free (etc) to its debug version using #define directives.
|
|
||||||
#define _CRTDBG_MAP_ALLOC
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <crtdbg.h>
|
|
||||||
// Replace operator new by trace-enabled version.
|
|
||||||
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
|
||||||
#define new DEBUG_NEW
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(FLATBUFFERS_ASSERT)
|
|
||||||
#include <assert.h>
|
|
||||||
#define FLATBUFFERS_ASSERT assert
|
|
||||||
#elif defined(FLATBUFFERS_ASSERT_INCLUDE)
|
|
||||||
// Include file with forward declaration
|
|
||||||
#include FLATBUFFERS_ASSERT_INCLUDE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ARDUINO
|
|
||||||
#include <cstdint>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) && defined(__AVR__)
|
|
||||||
#include <utility.h>
|
|
||||||
#else
|
|
||||||
#include <utility>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include <iterator>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#if defined(__unix__) && !defined(FLATBUFFERS_LOCALE_INDEPENDENT)
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
#include <android/api-level.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__ICCARM__)
|
|
||||||
#include <intrinsics.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Note the __clang__ check is needed, because clang presents itself
|
|
||||||
// as an older GNUC compiler (4.2).
|
|
||||||
// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
|
|
||||||
// Clang 3.4 and later implement all of the ISO C++ 2014 standard.
|
|
||||||
// http://clang.llvm.org/cxx_status.html
|
|
||||||
|
|
||||||
// Note the MSVC value '__cplusplus' may be incorrect:
|
|
||||||
// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L,
|
|
||||||
// indicating (erroneously!) that the compiler conformed to the C++98 Standard.
|
|
||||||
// This value should be correct starting from MSVC2017-15.7-Preview-3.
|
|
||||||
// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set.
|
|
||||||
// Workaround (for details see MSDN):
|
|
||||||
// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility.
|
|
||||||
// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch.
|
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_GCC 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_CLANG 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// @cond FLATBUFFERS_INTERNAL
|
|
||||||
#if __cplusplus <= 199711L && \
|
|
||||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
|
||||||
(!defined(__GNUC__) || \
|
|
||||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
|
|
||||||
#error A C++11 compatible compiler with support for the auto typing is \
|
|
||||||
required for FlatBuffers.
|
|
||||||
#error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__clang__) && \
|
|
||||||
defined(__GNUC__) && \
|
|
||||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
|
|
||||||
// Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr
|
|
||||||
// and constexpr keywords. Note the __clang__ check is needed, because clang
|
|
||||||
// presents itself as an older GNUC compiler.
|
|
||||||
#ifndef nullptr_t
|
|
||||||
const class nullptr_t {
|
|
||||||
public:
|
|
||||||
template<class T> inline operator T*() const { return 0; }
|
|
||||||
private:
|
|
||||||
void operator&() const;
|
|
||||||
} nullptr = {};
|
|
||||||
#endif
|
|
||||||
#ifndef constexpr
|
|
||||||
#define constexpr const
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The wire format uses a little endian encoding (since that's efficient for
|
|
||||||
// the common platforms).
|
|
||||||
#if defined(__s390x__)
|
|
||||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
|
||||||
#endif // __s390x__
|
|
||||||
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
|
||||||
#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
|
|
||||||
#if (defined(__BIG_ENDIAN__) || \
|
|
||||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
|
||||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_LITTLEENDIAN 1
|
|
||||||
#endif // __BIG_ENDIAN__
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
#if defined(_M_PPC)
|
|
||||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_LITTLEENDIAN 1
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
|
|
||||||
#endif
|
|
||||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
|
||||||
|
|
||||||
#define FLATBUFFERS_VERSION_MAJOR 25
|
|
||||||
#define FLATBUFFERS_VERSION_MINOR 12
|
|
||||||
#define FLATBUFFERS_VERSION_REVISION 19
|
|
||||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
|
||||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
|
||||||
namespace flatbuffers {
|
|
||||||
// Returns version as string "MAJOR.MINOR.REVISION".
|
|
||||||
const char* FLATBUFFERS_VERSION();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
|
|
||||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
|
|
||||||
defined(__clang__)
|
|
||||||
#define FLATBUFFERS_FINAL_CLASS final
|
|
||||||
#define FLATBUFFERS_OVERRIDE override
|
|
||||||
#define FLATBUFFERS_EXPLICIT_CPP11 explicit
|
|
||||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : ::flatbuffers::voffset_t
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_FINAL_CLASS
|
|
||||||
#define FLATBUFFERS_OVERRIDE
|
|
||||||
#define FLATBUFFERS_EXPLICIT_CPP11
|
|
||||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
|
|
||||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
|
|
||||||
(defined(__cpp_constexpr) && __cpp_constexpr >= 200704)
|
|
||||||
#define FLATBUFFERS_CONSTEXPR constexpr
|
|
||||||
#define FLATBUFFERS_CONSTEXPR_CPP11 constexpr
|
|
||||||
#define FLATBUFFERS_CONSTEXPR_DEFINED
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_CONSTEXPR const
|
|
||||||
#define FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
|
|
||||||
(defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
|
|
||||||
#define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_CONSTEXPR_CPP14
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
|
|
||||||
(defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \
|
|
||||||
defined(__clang__)
|
|
||||||
#define FLATBUFFERS_NOEXCEPT noexcept
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_NOEXCEPT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
|
|
||||||
// private, so be sure to put it at the end or reset access mode explicitly.
|
|
||||||
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
|
|
||||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
|
|
||||||
defined(__clang__)
|
|
||||||
#define FLATBUFFERS_DELETE_FUNC(func) func = delete
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_DELETE_FUNC(func) private: func
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
|
|
||||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
|
|
||||||
defined(__clang__)
|
|
||||||
#define FLATBUFFERS_DEFAULT_DECLARATION
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check if we can use template aliases
|
|
||||||
// Not possible if Microsoft Compiler before 2012
|
|
||||||
// Possible is the language feature __cpp_alias_templates is defined well
|
|
||||||
// Or possible if the C++ std is C+11 or newer
|
|
||||||
#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \
|
|
||||||
|| (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \
|
|
||||||
|| (defined(__cplusplus) && __cplusplus >= 201103L)
|
|
||||||
#define FLATBUFFERS_TEMPLATES_ALIASES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_HAS_STRING_VIEW
|
|
||||||
// Only provide flatbuffers::string_view if __has_include can be used
|
|
||||||
// to detect a header that provides an implementation
|
|
||||||
#if defined(__has_include)
|
|
||||||
// Check for std::string_view (in c++17)
|
|
||||||
#if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17))
|
|
||||||
#include <string_view>
|
|
||||||
namespace flatbuffers {
|
|
||||||
typedef std::string_view string_view;
|
|
||||||
}
|
|
||||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
|
||||||
// Check for std::experimental::string_view (in c++14, compiler-dependent)
|
|
||||||
#elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411)
|
|
||||||
#include <experimental/string_view>
|
|
||||||
namespace flatbuffers {
|
|
||||||
typedef std::experimental::string_view string_view;
|
|
||||||
}
|
|
||||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
|
||||||
// Check for absl::string_view
|
|
||||||
#elif __has_include("absl/strings/string_view.h") && \
|
|
||||||
__has_include("absl/base/config.h") && \
|
|
||||||
(__cplusplus >= 201411)
|
|
||||||
#include "absl/base/config.h"
|
|
||||||
#if !defined(ABSL_USES_STD_STRING_VIEW)
|
|
||||||
#include "absl/strings/string_view.h"
|
|
||||||
namespace flatbuffers {
|
|
||||||
typedef absl::string_view string_view;
|
|
||||||
}
|
|
||||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif // __has_include
|
|
||||||
#endif // !FLATBUFFERS_HAS_STRING_VIEW
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERAL_HEAP_ALLOC_OK
|
|
||||||
// Allow heap allocations to be used
|
|
||||||
#define FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 1
|
|
||||||
#endif // !FLATBUFFERS_GENERAL_HEAP_ALLOC_OK
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_HAS_NEW_STRTOD
|
|
||||||
// Modern (C++11) strtod and strtof functions are available for use.
|
|
||||||
// 1) nan/inf strings as argument of strtod;
|
|
||||||
// 2) hex-float as argument of strtod/strtof.
|
|
||||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
|
|
||||||
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
|
|
||||||
(defined(__clang__))
|
|
||||||
#define FLATBUFFERS_HAS_NEW_STRTOD 1
|
|
||||||
#endif
|
|
||||||
#endif // !FLATBUFFERS_HAS_NEW_STRTOD
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
|
|
||||||
// Enable locale independent functions {strtof_l, strtod_l,strtoll_l,
|
|
||||||
// strtoull_l} on platforms that support them.
|
|
||||||
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || \
|
|
||||||
(defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__>= 26) || \
|
|
||||||
(defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)) && \
|
|
||||||
!defined(__Fuchsia__)
|
|
||||||
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
|
|
||||||
#endif
|
|
||||||
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
|
|
||||||
|
|
||||||
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
|
|
||||||
// - FLATBUFFERS_SUPPRESS_UBSAN("undefined")
|
|
||||||
// - FLATBUFFERS_SUPPRESS_UBSAN("signed-integer-overflow")
|
|
||||||
#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
|
|
||||||
#define FLATBUFFERS_SUPPRESS_UBSAN(type) __attribute__((no_sanitize(type)))
|
|
||||||
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
|
|
||||||
#define FLATBUFFERS_SUPPRESS_UBSAN(type) __attribute__((no_sanitize_undefined))
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_SUPPRESS_UBSAN(type)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
// This is constexpr function used for checking compile-time constants.
|
|
||||||
// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
|
|
||||||
template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
|
|
||||||
return !!t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable C++ attribute [[]] if std:c++17 or higher.
|
|
||||||
#if ((__cplusplus >= 201703L) \
|
|
||||||
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
|
|
||||||
// All attributes unknown to an implementation are ignored without causing an error.
|
|
||||||
#define FLATBUFFERS_ATTRIBUTE(attr) attr
|
|
||||||
|
|
||||||
#define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_ATTRIBUTE(attr)
|
|
||||||
|
|
||||||
#if FLATBUFFERS_CLANG >= 30800
|
|
||||||
#define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]]
|
|
||||||
#elif FLATBUFFERS_GCC >= 70300
|
|
||||||
#define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]]
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_FALLTHROUGH()
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// @endcond
|
|
||||||
|
|
||||||
/// @file
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
/// @cond FLATBUFFERS_INTERNAL
|
|
||||||
// Our default offset / size type, 32bit on purpose on 64bit systems.
|
|
||||||
// Also, using a consistent offset type maintains compatibility of serialized
|
|
||||||
// offset values between 32bit and 64bit systems.
|
|
||||||
typedef uint32_t uoffset_t;
|
|
||||||
typedef uint64_t uoffset64_t;
|
|
||||||
|
|
||||||
// Signed offsets for references that can go in both directions.
|
|
||||||
typedef int32_t soffset_t;
|
|
||||||
typedef int64_t soffset64_t;
|
|
||||||
|
|
||||||
// Offset/index used in v-tables, can be changed to uint8_t in
|
|
||||||
// format forks to save a bit of space if desired.
|
|
||||||
typedef uint16_t voffset_t;
|
|
||||||
|
|
||||||
typedef uintmax_t largest_scalar_t;
|
|
||||||
|
|
||||||
// In 32bits, this evaluates to 2GB - 1
|
|
||||||
#define FLATBUFFERS_MAX_BUFFER_SIZE (std::numeric_limits<::flatbuffers::soffset_t>::max)()
|
|
||||||
#define FLATBUFFERS_MAX_64_BUFFER_SIZE (std::numeric_limits<::flatbuffers::soffset64_t>::max)()
|
|
||||||
|
|
||||||
// The minimum size buffer that can be a valid flatbuffer.
|
|
||||||
// Includes the offset to the root table (uoffset_t), the offset to the vtable
|
|
||||||
// of the root table (soffset_t), the size of the vtable (uint16_t), and the
|
|
||||||
// size of the referring table (uint16_t).
|
|
||||||
#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(::flatbuffers::uoffset_t) + \
|
|
||||||
sizeof(::flatbuffers::soffset_t) + sizeof(uint16_t) + sizeof(uint16_t)
|
|
||||||
|
|
||||||
// We support aligning the contents of buffers up to this size.
|
|
||||||
#ifndef FLATBUFFERS_MAX_ALIGNMENT
|
|
||||||
#define FLATBUFFERS_MAX_ALIGNMENT 32
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// @brief The length of a FlatBuffer file header.
|
|
||||||
static const size_t kFileIdentifierLength = 4;
|
|
||||||
|
|
||||||
inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) {
|
|
||||||
return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) &&
|
|
||||||
(align & (align - 1)) == 0; // must be power of 2
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<typename T> T EndianSwap(T t) {
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
|
|
||||||
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
|
|
||||||
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
|
|
||||||
#elif defined(__ICCARM__)
|
|
||||||
#define FLATBUFFERS_BYTESWAP16 __REV16
|
|
||||||
#define FLATBUFFERS_BYTESWAP32 __REV
|
|
||||||
#define FLATBUFFERS_BYTESWAP64(x) \
|
|
||||||
((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U)
|
|
||||||
#else
|
|
||||||
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
|
|
||||||
// __builtin_bswap16 was missing prior to GCC 4.8.
|
|
||||||
#define FLATBUFFERS_BYTESWAP16(x) \
|
|
||||||
static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
|
|
||||||
#endif
|
|
||||||
#define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
|
|
||||||
#define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
|
|
||||||
#endif
|
|
||||||
if (sizeof(T) == 1) { // Compile-time if-then's.
|
|
||||||
return t;
|
|
||||||
} else if (sizeof(T) == 2) {
|
|
||||||
union { T t; uint16_t i; } u = { t };
|
|
||||||
u.i = FLATBUFFERS_BYTESWAP16(u.i);
|
|
||||||
return u.t;
|
|
||||||
} else if (sizeof(T) == 4) {
|
|
||||||
union { T t; uint32_t i; } u = { t };
|
|
||||||
u.i = FLATBUFFERS_BYTESWAP32(u.i);
|
|
||||||
return u.t;
|
|
||||||
} else if (sizeof(T) == 8) {
|
|
||||||
union { T t; uint64_t i; } u = { t };
|
|
||||||
u.i = FLATBUFFERS_BYTESWAP64(u.i);
|
|
||||||
return u.t;
|
|
||||||
} else {
|
|
||||||
FLATBUFFERS_ASSERT(0);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T> T EndianScalar(T t) {
|
|
||||||
#if FLATBUFFERS_LITTLEENDIAN
|
|
||||||
return t;
|
|
||||||
#else
|
|
||||||
return EndianSwap(t);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
|
||||||
FLATBUFFERS_SUPPRESS_UBSAN("alignment")
|
|
||||||
T ReadScalar(const void *p) {
|
|
||||||
return EndianScalar(*reinterpret_cast<const T *>(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
// See https://github.com/google/flatbuffers/issues/5950
|
|
||||||
|
|
||||||
#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
|
||||||
FLATBUFFERS_SUPPRESS_UBSAN("alignment")
|
|
||||||
void WriteScalar(void *p, T t) {
|
|
||||||
*reinterpret_cast<T *>(p) = EndianScalar(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> struct Offset;
|
|
||||||
template<typename T> FLATBUFFERS_SUPPRESS_UBSAN("alignment") void WriteScalar(void *p, Offset<T> t) {
|
|
||||||
*reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Computes how many bytes you'd have to pad to be able to write an
|
|
||||||
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
|
|
||||||
// memory).
|
|
||||||
FLATBUFFERS_SUPPRESS_UBSAN("unsigned-integer-overflow")
|
|
||||||
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
|
||||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(_MSC_VER)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
|
||||||
#endif
|
|
||||||
// Generic 'operator==' with conditional specialisations.
|
|
||||||
// T e - new value of a scalar field.
|
|
||||||
// T def - default of scalar (is known at compile-time).
|
|
||||||
template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
|
|
||||||
#if !defined(_MSC_VER)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
|
|
||||||
defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
|
|
||||||
// Like `operator==(e, def)` with weak NaN if T=(float|double).
|
|
||||||
template<typename T> inline bool IsFloatTheSameAs(T e, T def) {
|
|
||||||
return (e == def) || ((def != def) && (e != e));
|
|
||||||
}
|
|
||||||
template<> inline bool IsTheSameAs<float>(float e, float def) {
|
|
||||||
return IsFloatTheSameAs(e, def);
|
|
||||||
}
|
|
||||||
template<> inline bool IsTheSameAs<double>(double e, double def) {
|
|
||||||
return IsFloatTheSameAs(e, def);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check 'v' is out of closed range [low; high].
|
|
||||||
// Workaround for GCC warning [-Werror=type-limits]:
|
|
||||||
// comparison is always true due to limited range of data type.
|
|
||||||
template<typename T>
|
|
||||||
inline bool IsOutRange(const T &v, const T &low, const T &high) {
|
|
||||||
return (v < low) || (high < v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check 'v' is in closed range [low; high].
|
|
||||||
template<typename T>
|
|
||||||
inline bool IsInRange(const T &v, const T &low, const T &high) {
|
|
||||||
return !IsOutRange(v, low, high);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
#endif // FLATBUFFERS_BASE_H_
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_BUFFER_H_
|
|
||||||
#define FLATBUFFERS_BUFFER_H_
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/stl_emulation.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Wrapper for uoffset_t to allow safe template specialization.
|
|
||||||
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
|
|
||||||
template <typename T = void>
|
|
||||||
struct Offset {
|
|
||||||
// The type of offset to use.
|
|
||||||
typedef uoffset_t offset_type;
|
|
||||||
|
|
||||||
offset_type o;
|
|
||||||
Offset() : o(0) {}
|
|
||||||
Offset(const offset_type _o) : o(_o) {}
|
|
||||||
Offset<> Union() const { return o; }
|
|
||||||
bool IsNull() const { return !o; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_specialisation_of_Offset : false_type {};
|
|
||||||
template <typename T>
|
|
||||||
struct is_specialisation_of_Offset<Offset<T>> : true_type {};
|
|
||||||
|
|
||||||
// Wrapper for uoffset64_t Offsets.
|
|
||||||
template <typename T = void>
|
|
||||||
struct Offset64 {
|
|
||||||
// The type of offset to use.
|
|
||||||
typedef uoffset64_t offset_type;
|
|
||||||
|
|
||||||
offset_type o;
|
|
||||||
Offset64() : o(0) {}
|
|
||||||
Offset64(const offset_type offset) : o(offset) {}
|
|
||||||
Offset64<> Union() const { return o; }
|
|
||||||
bool IsNull() const { return !o; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_specialisation_of_Offset64 : false_type {};
|
|
||||||
template <typename T>
|
|
||||||
struct is_specialisation_of_Offset64<Offset64<T>> : true_type {};
|
|
||||||
|
|
||||||
// Litmus check for ensuring the Offsets are the expected size.
|
|
||||||
static_assert(sizeof(Offset<>) == 4, "Offset has wrong size");
|
|
||||||
static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size");
|
|
||||||
|
|
||||||
inline void EndianCheck() {
|
|
||||||
int endiantest = 1;
|
|
||||||
// If this fails, see FLATBUFFERS_LITTLEENDIAN above.
|
|
||||||
FLATBUFFERS_ASSERT(*reinterpret_cast<char*>(&endiantest) ==
|
|
||||||
FLATBUFFERS_LITTLEENDIAN);
|
|
||||||
(void)endiantest;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
FLATBUFFERS_CONSTEXPR size_t AlignOf() {
|
|
||||||
// clang-format off
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
return __alignof(T);
|
|
||||||
#else
|
|
||||||
#ifndef alignof
|
|
||||||
return __alignof__(T);
|
|
||||||
#else
|
|
||||||
return alignof(T);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lexicographically compare two strings (possibly containing nulls), and
|
|
||||||
// return true if the first is less than the second.
|
|
||||||
static inline bool StringLessThan(const char* a_data, uoffset_t a_size,
|
|
||||||
const char* b_data, uoffset_t b_size) {
|
|
||||||
const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
|
|
||||||
return cmp == 0 ? a_size < b_size : cmp < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When we read serialized data from memory, in the case of most scalars,
|
|
||||||
// we want to just read T, but in the case of Offset, we want to actually
|
|
||||||
// perform the indirection and return a pointer.
|
|
||||||
// The template specialization below does just that.
|
|
||||||
// It is wrapped in a struct since function templates can't overload on the
|
|
||||||
// return type like this.
|
|
||||||
// The typedef is for the convenience of callers of this function
|
|
||||||
// (avoiding the need for a trailing return decltype)
|
|
||||||
template <typename T, typename Enable = void>
|
|
||||||
struct IndirectHelper {
|
|
||||||
typedef T return_type;
|
|
||||||
typedef T mutable_return_type;
|
|
||||||
static const size_t element_stride = sizeof(T);
|
|
||||||
|
|
||||||
static return_type Read(const uint8_t* p, const size_t i) {
|
|
||||||
return EndianScalar((reinterpret_cast<const T*>(p))[i]);
|
|
||||||
}
|
|
||||||
static mutable_return_type Read(uint8_t* p, const size_t i) {
|
|
||||||
return reinterpret_cast<mutable_return_type>(
|
|
||||||
Read(const_cast<const uint8_t*>(p), i));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// For vector of Offsets.
|
|
||||||
template <typename T, template <typename> class OffsetT>
|
|
||||||
struct IndirectHelper<OffsetT<T>> {
|
|
||||||
typedef const T* return_type;
|
|
||||||
typedef T* mutable_return_type;
|
|
||||||
typedef typename OffsetT<T>::offset_type offset_type;
|
|
||||||
static const offset_type element_stride = sizeof(offset_type);
|
|
||||||
|
|
||||||
static return_type Read(const uint8_t* const p, const offset_type i) {
|
|
||||||
// Offsets are relative to themselves, so first update the pointer to
|
|
||||||
// point to the offset location.
|
|
||||||
const uint8_t* const offset_location = p + i * element_stride;
|
|
||||||
|
|
||||||
// Then read the scalar value of the offset (which may be 32 or 64-bits) and
|
|
||||||
// then determine the relative location from the offset location.
|
|
||||||
return reinterpret_cast<return_type>(
|
|
||||||
offset_location + ReadScalar<offset_type>(offset_location));
|
|
||||||
}
|
|
||||||
static mutable_return_type Read(uint8_t* const p, const offset_type i) {
|
|
||||||
// Offsets are relative to themselves, so first update the pointer to
|
|
||||||
// point to the offset location.
|
|
||||||
uint8_t* const offset_location = p + i * element_stride;
|
|
||||||
|
|
||||||
// Then read the scalar value of the offset (which may be 32 or 64-bits) and
|
|
||||||
// then determine the relative location from the offset location.
|
|
||||||
return reinterpret_cast<mutable_return_type>(
|
|
||||||
offset_location + ReadScalar<offset_type>(offset_location));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// For vector of structs.
|
|
||||||
template <typename T>
|
|
||||||
struct IndirectHelper<
|
|
||||||
T, typename std::enable_if<
|
|
||||||
!std::is_scalar<typename std::remove_pointer<T>::type>::value &&
|
|
||||||
!is_specialisation_of_Offset<T>::value &&
|
|
||||||
!is_specialisation_of_Offset64<T>::value>::type> {
|
|
||||||
private:
|
|
||||||
typedef typename std::remove_pointer<typename std::remove_cv<T>::type>::type
|
|
||||||
pointee_type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef const pointee_type* return_type;
|
|
||||||
typedef pointee_type* mutable_return_type;
|
|
||||||
static const size_t element_stride = sizeof(pointee_type);
|
|
||||||
|
|
||||||
static return_type Read(const uint8_t* const p, const size_t i) {
|
|
||||||
// Structs are stored inline, relative to the first struct pointer.
|
|
||||||
return reinterpret_cast<return_type>(p + i * element_stride);
|
|
||||||
}
|
|
||||||
static mutable_return_type Read(uint8_t* const p, const size_t i) {
|
|
||||||
// Structs are stored inline, relative to the first struct pointer.
|
|
||||||
return reinterpret_cast<mutable_return_type>(p + i * element_stride);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief Get a pointer to the file_identifier section of the buffer.
|
|
||||||
/// @return Returns a const char pointer to the start of the file_identifier
|
|
||||||
/// characters in the buffer. The returned char * has length
|
|
||||||
/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
|
|
||||||
/// This function is UNDEFINED for FlatBuffers whose schema does not include
|
|
||||||
/// a file_identifier (likely points at padding or the start of a the root
|
|
||||||
/// vtable).
|
|
||||||
inline const char* GetBufferIdentifier(const void* buf,
|
|
||||||
bool size_prefixed = false) {
|
|
||||||
return reinterpret_cast<const char*>(buf) +
|
|
||||||
((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper to see if the identifier in a buffer has the expected value.
|
|
||||||
inline bool BufferHasIdentifier(const void* buf, const char* identifier,
|
|
||||||
bool size_prefixed = false) {
|
|
||||||
return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
|
|
||||||
flatbuffers::kFileIdentifierLength) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @cond FLATBUFFERS_INTERNAL
|
|
||||||
// Helpers to get a typed pointer to the root object contained in the buffer.
|
|
||||||
template <typename T>
|
|
||||||
T* GetMutableRoot(void* buf) {
|
|
||||||
if (!buf) return nullptr;
|
|
||||||
EndianCheck();
|
|
||||||
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(buf) +
|
|
||||||
EndianScalar(*reinterpret_cast<uoffset_t*>(buf)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename SizeT = uoffset_t>
|
|
||||||
T* GetMutableSizePrefixedRoot(void* buf) {
|
|
||||||
return GetMutableRoot<T>(reinterpret_cast<uint8_t*>(buf) + sizeof(SizeT));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
const T* GetRoot(const void* buf) {
|
|
||||||
return GetMutableRoot<T>(const_cast<void*>(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename SizeT = uoffset_t>
|
|
||||||
const T* GetSizePrefixedRoot(const void* buf) {
|
|
||||||
return GetRoot<T>(reinterpret_cast<const uint8_t*>(buf) + sizeof(SizeT));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_BUFFER_H_
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_BUFFER_REF_H_
|
|
||||||
#define FLATBUFFERS_BUFFER_REF_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/verifier.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Convenient way to bundle a buffer and its length, to pass it around
|
|
||||||
// typed by its root.
|
|
||||||
// A BufferRef does not own its buffer.
|
|
||||||
struct BufferRefBase {}; // for std::is_base_of
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct BufferRef : BufferRefBase {
|
|
||||||
BufferRef() : buf(nullptr), len(0), must_free(false) {}
|
|
||||||
BufferRef(uint8_t* _buf, uoffset_t _len)
|
|
||||||
: buf(_buf), len(_len), must_free(false) {}
|
|
||||||
|
|
||||||
~BufferRef() {
|
|
||||||
if (must_free) free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
const T* GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
|
|
||||||
|
|
||||||
bool Verify() {
|
|
||||||
Verifier verifier(buf, len);
|
|
||||||
return verifier.VerifyBuffer<T>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* buf;
|
|
||||||
uoffset_t len;
|
|
||||||
bool must_free;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_BUFFER_REF_H_
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_CODE_GENERATOR_H_
|
|
||||||
#define FLATBUFFERS_CODE_GENERATOR_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "flatbuffers/file_manager.h"
|
|
||||||
#include "flatbuffers/idl.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
struct CodeGenOptions {
|
|
||||||
std::string output_path;
|
|
||||||
FileSaver* file_saver{nullptr};
|
|
||||||
};
|
|
||||||
|
|
||||||
// A code generator interface for producing converting flatbuffer schema into
|
|
||||||
// code.
|
|
||||||
class CodeGenerator {
|
|
||||||
public:
|
|
||||||
virtual ~CodeGenerator() = default;
|
|
||||||
|
|
||||||
enum Status {
|
|
||||||
OK = 0,
|
|
||||||
ERROR = 1,
|
|
||||||
FAILED_VERIFICATION = 2,
|
|
||||||
NOT_IMPLEMENTED = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string status_detail;
|
|
||||||
|
|
||||||
// Generate code from the provided `parser`.
|
|
||||||
//
|
|
||||||
// DEPRECATED: prefer using the other overload of GenerateCode for bfbs.
|
|
||||||
virtual Status GenerateCode(const Parser& parser, const std::string& path,
|
|
||||||
const std::string& filename) = 0;
|
|
||||||
|
|
||||||
// Generate code from the provided `parser` and place it in the output.
|
|
||||||
virtual Status GenerateCodeString(const Parser& parser,
|
|
||||||
const std::string& filename,
|
|
||||||
std::string& output) {
|
|
||||||
(void)parser;
|
|
||||||
(void)filename;
|
|
||||||
(void)output;
|
|
||||||
return Status::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate code from the provided `buffer` of given `length`. The buffer is a
|
|
||||||
// serialized reflection.fbs.
|
|
||||||
virtual Status GenerateCode(const uint8_t* buffer, int64_t length,
|
|
||||||
const CodeGenOptions& options) = 0;
|
|
||||||
|
|
||||||
virtual Status GenerateMakeRule(const Parser& parser, const std::string& path,
|
|
||||||
const std::string& filename,
|
|
||||||
std::string& output) = 0;
|
|
||||||
|
|
||||||
virtual Status GenerateGrpcCode(const Parser& parser, const std::string& path,
|
|
||||||
const std::string& filename) = 0;
|
|
||||||
|
|
||||||
virtual Status GenerateRootFile(const Parser& parser,
|
|
||||||
const std::string& path) = 0;
|
|
||||||
|
|
||||||
virtual bool IsSchemaOnly() const = 0;
|
|
||||||
|
|
||||||
virtual bool SupportsBfbsGeneration() const = 0;
|
|
||||||
|
|
||||||
virtual bool SupportsRootFileGeneration() const = 0;
|
|
||||||
|
|
||||||
virtual IDLOptions::Language Language() const = 0;
|
|
||||||
|
|
||||||
virtual std::string LanguageName() const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
CodeGenerator() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Copying is not supported.
|
|
||||||
CodeGenerator(const CodeGenerator&) = delete;
|
|
||||||
CodeGenerator& operator=(const CodeGenerator&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_CODE_GENERATOR_H_
|
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_CODE_GENERATORS_H_
|
|
||||||
#define FLATBUFFERS_CODE_GENERATORS_H_
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "flatbuffers/idl.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Utility class to assist in generating code through use of text templates.
|
|
||||||
//
|
|
||||||
// Example code:
|
|
||||||
// CodeWriter code("\t");
|
|
||||||
// code.SetValue("NAME", "Foo");
|
|
||||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
|
||||||
// code.SetValue("NAME", "Bar");
|
|
||||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
|
||||||
// std::cout << code.ToString() << std::endl;
|
|
||||||
//
|
|
||||||
// Output:
|
|
||||||
// void Foo() { printf("%s", "Foo"); }
|
|
||||||
// void Bar() { printf("%s", "Bar"); }
|
|
||||||
class CodeWriter {
|
|
||||||
public:
|
|
||||||
CodeWriter(std::string pad = std::string())
|
|
||||||
: pad_(pad), cur_ident_lvl_(0), ignore_ident_(false) {}
|
|
||||||
|
|
||||||
// Clears the current "written" code.
|
|
||||||
void Clear() {
|
|
||||||
stream_.str("");
|
|
||||||
stream_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Associates a key with a value. All subsequent calls to operator+=, where
|
|
||||||
// the specified key is contained in {{ and }} delimiters will be replaced by
|
|
||||||
// the given value.
|
|
||||||
void SetValue(const std::string& key, const std::string& value) {
|
|
||||||
value_map_[key] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetValue(const std::string& key) const {
|
|
||||||
const auto it = value_map_.find(key);
|
|
||||||
return it == value_map_.end() ? "" : it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Appends the given text to the generated code as well as a newline
|
|
||||||
// character. Any text within {{ and }} delimiters is replaced by values
|
|
||||||
// previously stored in the CodeWriter by calling SetValue above. The newline
|
|
||||||
// will be suppressed if the text ends with the \\ character.
|
|
||||||
void operator+=(std::string text);
|
|
||||||
|
|
||||||
// Returns the current contents of the CodeWriter as a std::string.
|
|
||||||
std::string ToString() const { return stream_.str(); }
|
|
||||||
|
|
||||||
// Increase ident level for writing code
|
|
||||||
void IncrementIdentLevel() { cur_ident_lvl_++; }
|
|
||||||
// Decrease ident level for writing code
|
|
||||||
void DecrementIdentLevel() {
|
|
||||||
if (cur_ident_lvl_) cur_ident_lvl_--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPadding(const std::string& padding) { pad_ = padding; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<std::string, std::string> value_map_;
|
|
||||||
std::stringstream stream_;
|
|
||||||
std::string pad_;
|
|
||||||
int cur_ident_lvl_;
|
|
||||||
bool ignore_ident_;
|
|
||||||
|
|
||||||
// Add ident padding (tab or space) based on ident level
|
|
||||||
void AppendIdent(std::stringstream& stream);
|
|
||||||
};
|
|
||||||
|
|
||||||
class BaseGenerator {
|
|
||||||
public:
|
|
||||||
virtual bool generate() = 0;
|
|
||||||
|
|
||||||
static std::string NamespaceDir(const Parser& parser, const std::string& path,
|
|
||||||
const Namespace& ns,
|
|
||||||
const bool dasherize = false);
|
|
||||||
|
|
||||||
std::string GeneratedFileName(const std::string& path,
|
|
||||||
const std::string& file_name,
|
|
||||||
const IDLOptions& options) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
BaseGenerator(const Parser& parser, const std::string& path,
|
|
||||||
const std::string& file_name, std::string qualifying_start,
|
|
||||||
std::string qualifying_separator, std::string default_extension)
|
|
||||||
: parser_(parser),
|
|
||||||
path_(path),
|
|
||||||
file_name_(file_name),
|
|
||||||
qualifying_start_(qualifying_start),
|
|
||||||
qualifying_separator_(qualifying_separator),
|
|
||||||
default_extension_(default_extension) {}
|
|
||||||
virtual ~BaseGenerator() {}
|
|
||||||
|
|
||||||
// No copy/assign.
|
|
||||||
BaseGenerator& operator=(const BaseGenerator&);
|
|
||||||
BaseGenerator(const BaseGenerator&);
|
|
||||||
|
|
||||||
std::string NamespaceDir(const Namespace& ns,
|
|
||||||
const bool dasherize = false) const;
|
|
||||||
|
|
||||||
static const char* FlatBuffersGeneratedWarning();
|
|
||||||
|
|
||||||
static std::string FullNamespace(const char* separator, const Namespace& ns);
|
|
||||||
|
|
||||||
static std::string LastNamespacePart(const Namespace& ns);
|
|
||||||
|
|
||||||
// tracks the current namespace for early exit in WrapInNameSpace
|
|
||||||
// c++, java and csharp returns a different namespace from
|
|
||||||
// the following default (no early exit, always fully qualify),
|
|
||||||
// which works for js and php
|
|
||||||
virtual const Namespace* CurrentNameSpace() const { return nullptr; }
|
|
||||||
|
|
||||||
// Ensure that a type is prefixed with its namespace even within
|
|
||||||
// its own namespace to avoid conflict between generated method
|
|
||||||
// names and similarly named classes or structs
|
|
||||||
std::string WrapInNameSpace(const Namespace* ns,
|
|
||||||
const std::string& name) const;
|
|
||||||
|
|
||||||
std::string WrapInNameSpace(const Definition& def,
|
|
||||||
const std::string& suffix = "") const;
|
|
||||||
|
|
||||||
std::string GetNameSpace(const Definition& def) const;
|
|
||||||
|
|
||||||
const Parser& parser_;
|
|
||||||
const std::string& path_;
|
|
||||||
const std::string& file_name_;
|
|
||||||
const std::string qualifying_start_;
|
|
||||||
const std::string qualifying_separator_;
|
|
||||||
const std::string default_extension_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CommentConfig {
|
|
||||||
const char* first_line;
|
|
||||||
const char* content_line_prefix;
|
|
||||||
const char* last_line;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void GenComment(const std::vector<std::string>& dc,
|
|
||||||
std::string* code_ptr, const CommentConfig* config,
|
|
||||||
const char* prefix = "");
|
|
||||||
|
|
||||||
class FloatConstantGenerator {
|
|
||||||
public:
|
|
||||||
virtual ~FloatConstantGenerator() {}
|
|
||||||
std::string GenFloatConstant(const FieldDef& field) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual std::string Value(double v, const std::string& src) const = 0;
|
|
||||||
virtual std::string Inf(double v) const = 0;
|
|
||||||
virtual std::string NaN(double v) const = 0;
|
|
||||||
|
|
||||||
virtual std::string Value(float v, const std::string& src) const = 0;
|
|
||||||
virtual std::string Inf(float v) const = 0;
|
|
||||||
virtual std::string NaN(float v) const = 0;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::string GenFloatConstantImpl(const FieldDef& field) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SimpleFloatConstantGenerator : public FloatConstantGenerator {
|
|
||||||
public:
|
|
||||||
SimpleFloatConstantGenerator(const char* nan_number,
|
|
||||||
const char* pos_inf_number,
|
|
||||||
const char* neg_inf_number);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string Value(double v,
|
|
||||||
const std::string& src) const FLATBUFFERS_OVERRIDE;
|
|
||||||
std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
|
|
||||||
std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
|
|
||||||
|
|
||||||
std::string Value(float v, const std::string& src) const FLATBUFFERS_OVERRIDE;
|
|
||||||
std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
|
|
||||||
std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
|
|
||||||
|
|
||||||
const std::string nan_number_;
|
|
||||||
const std::string pos_inf_number_;
|
|
||||||
const std::string neg_inf_number_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// C++, C#, Java like generator.
|
|
||||||
class TypedFloatConstantGenerator : public FloatConstantGenerator {
|
|
||||||
public:
|
|
||||||
TypedFloatConstantGenerator(const char* double_prefix,
|
|
||||||
const char* single_prefix, const char* nan_number,
|
|
||||||
const char* pos_inf_number,
|
|
||||||
const char* neg_inf_number = "");
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string Value(double v,
|
|
||||||
const std::string& src) const FLATBUFFERS_OVERRIDE;
|
|
||||||
std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
|
|
||||||
|
|
||||||
std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
|
|
||||||
|
|
||||||
std::string Value(float v, const std::string& src) const FLATBUFFERS_OVERRIDE;
|
|
||||||
std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
|
|
||||||
std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
|
|
||||||
|
|
||||||
std::string MakeNaN(const std::string& prefix) const;
|
|
||||||
std::string MakeInf(bool neg, const std::string& prefix) const;
|
|
||||||
|
|
||||||
const std::string double_prefix_;
|
|
||||||
const std::string single_prefix_;
|
|
||||||
const std::string nan_number_;
|
|
||||||
const std::string pos_inf_number_;
|
|
||||||
const std::string neg_inf_number_;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string JavaCSharpMakeRule(const bool java, const Parser& parser,
|
|
||||||
const std::string& path,
|
|
||||||
const std::string& file_name);
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_CODE_GENERATORS_H_
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_DEFAULT_ALLOCATOR_H_
|
|
||||||
#define FLATBUFFERS_DEFAULT_ALLOCATOR_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/allocator.h"
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// DefaultAllocator uses new/delete to allocate memory regions
|
|
||||||
class DefaultAllocator : public Allocator {
|
|
||||||
public:
|
|
||||||
uint8_t* allocate(size_t size) FLATBUFFERS_OVERRIDE {
|
|
||||||
return new uint8_t[size];
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate(uint8_t* p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; }
|
|
||||||
|
|
||||||
static void dealloc(void* p, size_t) { delete[] static_cast<uint8_t*>(p); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// These functions allow for a null allocator to mean use the default allocator,
|
|
||||||
// as used by DetachedBuffer and vector_downward below.
|
|
||||||
// This is to avoid having a statically or dynamically allocated default
|
|
||||||
// allocator, or having to move it between the classes that may own it.
|
|
||||||
inline uint8_t* Allocate(Allocator* allocator, size_t size) {
|
|
||||||
return allocator ? allocator->allocate(size)
|
|
||||||
: DefaultAllocator().allocate(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Deallocate(Allocator* allocator, uint8_t* p, size_t size) {
|
|
||||||
if (allocator)
|
|
||||||
allocator->deallocate(p, size);
|
|
||||||
else
|
|
||||||
DefaultAllocator().deallocate(p, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t* ReallocateDownward(Allocator* allocator, uint8_t* old_p,
|
|
||||||
size_t old_size, size_t new_size,
|
|
||||||
size_t in_use_back, size_t in_use_front) {
|
|
||||||
return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
|
|
||||||
in_use_back, in_use_front)
|
|
||||||
: DefaultAllocator().reallocate_downward(
|
|
||||||
old_p, old_size, new_size, in_use_back, in_use_front);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_DEFAULT_ALLOCATOR_H_
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_DETACHED_BUFFER_H_
|
|
||||||
#define FLATBUFFERS_DETACHED_BUFFER_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/allocator.h"
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/default_allocator.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// DetachedBuffer is a finished flatbuffer memory region, detached from its
|
|
||||||
// builder. The original memory region and allocator are also stored so that
|
|
||||||
// the DetachedBuffer can manage the memory lifetime.
|
|
||||||
class DetachedBuffer {
|
|
||||||
public:
|
|
||||||
DetachedBuffer()
|
|
||||||
: allocator_(nullptr),
|
|
||||||
own_allocator_(false),
|
|
||||||
buf_(nullptr),
|
|
||||||
reserved_(0),
|
|
||||||
cur_(nullptr),
|
|
||||||
size_(0) {}
|
|
||||||
|
|
||||||
DetachedBuffer(Allocator* allocator, bool own_allocator, uint8_t* buf,
|
|
||||||
size_t reserved, uint8_t* cur, size_t sz)
|
|
||||||
: allocator_(allocator),
|
|
||||||
own_allocator_(own_allocator),
|
|
||||||
buf_(buf),
|
|
||||||
reserved_(reserved),
|
|
||||||
cur_(cur),
|
|
||||||
size_(sz) {}
|
|
||||||
|
|
||||||
DetachedBuffer(DetachedBuffer&& other) noexcept
|
|
||||||
: allocator_(other.allocator_),
|
|
||||||
own_allocator_(other.own_allocator_),
|
|
||||||
buf_(other.buf_),
|
|
||||||
reserved_(other.reserved_),
|
|
||||||
cur_(other.cur_),
|
|
||||||
size_(other.size_) {
|
|
||||||
other.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
DetachedBuffer& operator=(DetachedBuffer&& other) noexcept {
|
|
||||||
if (this == &other) return *this;
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
allocator_ = other.allocator_;
|
|
||||||
own_allocator_ = other.own_allocator_;
|
|
||||||
buf_ = other.buf_;
|
|
||||||
reserved_ = other.reserved_;
|
|
||||||
cur_ = other.cur_;
|
|
||||||
size_ = other.size_;
|
|
||||||
|
|
||||||
other.reset();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~DetachedBuffer() { destroy(); }
|
|
||||||
|
|
||||||
const uint8_t* data() const { return cur_; }
|
|
||||||
|
|
||||||
uint8_t* data() { return cur_; }
|
|
||||||
|
|
||||||
size_t size() const { return size_; }
|
|
||||||
|
|
||||||
uint8_t* begin() { return data(); }
|
|
||||||
const uint8_t* begin() const { return data(); }
|
|
||||||
uint8_t* end() { return data() + size(); }
|
|
||||||
const uint8_t* end() const { return data() + size(); }
|
|
||||||
|
|
||||||
// These may change access mode, leave these at end of public section
|
|
||||||
FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer& other));
|
|
||||||
FLATBUFFERS_DELETE_FUNC(
|
|
||||||
DetachedBuffer& operator=(const DetachedBuffer& other));
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Allocator* allocator_;
|
|
||||||
bool own_allocator_;
|
|
||||||
uint8_t* buf_;
|
|
||||||
size_t reserved_;
|
|
||||||
uint8_t* cur_;
|
|
||||||
size_t size_;
|
|
||||||
|
|
||||||
inline void destroy() {
|
|
||||||
if (buf_) Deallocate(allocator_, buf_, reserved_);
|
|
||||||
if (own_allocator_ && allocator_) {
|
|
||||||
delete allocator_;
|
|
||||||
}
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void reset() {
|
|
||||||
allocator_ = nullptr;
|
|
||||||
own_allocator_ = false;
|
|
||||||
buf_ = nullptr;
|
|
||||||
reserved_ = 0;
|
|
||||||
cur_ = nullptr;
|
|
||||||
size_ = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_DETACHED_BUFFER_H_
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_FILE_MANAGER_H_
|
|
||||||
#define FLATBUFFERS_FILE_MANAGER_H_
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// A File interface to write data to file by default or
|
|
||||||
// save only file names
|
|
||||||
class FileSaver {
|
|
||||||
public:
|
|
||||||
FileSaver() = default;
|
|
||||||
virtual ~FileSaver() = default;
|
|
||||||
|
|
||||||
virtual bool SaveFile(const char* name, const char* buf, size_t len,
|
|
||||||
bool binary) = 0;
|
|
||||||
|
|
||||||
bool SaveFile(const char* name, const std::string& buf, bool binary) {
|
|
||||||
return SaveFile(name, buf.c_str(), buf.size(), binary);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Finish() {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Copying is not supported.
|
|
||||||
FileSaver(const FileSaver&) = delete;
|
|
||||||
FileSaver& operator=(const FileSaver&) = delete;
|
|
||||||
// Rule of 5
|
|
||||||
FileSaver(FileSaver&&) = default;
|
|
||||||
FileSaver& operator=(FileSaver&&) = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RealFileSaver final : public FileSaver {
|
|
||||||
public:
|
|
||||||
bool SaveFile(const char* name, const char* buf, size_t len,
|
|
||||||
bool binary) final;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FileNameSaver final : public FileSaver {
|
|
||||||
public:
|
|
||||||
bool SaveFile(const char* name, const char* buf, size_t len,
|
|
||||||
bool binary) final;
|
|
||||||
|
|
||||||
void Finish() final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::set<std::string> file_names_{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_FILE_MANAGER_H_
|
|
||||||
-1518
File diff suppressed because it is too large
Load Diff
@@ -1,284 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_H_
|
|
||||||
#define FLATBUFFERS_H_
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
// TODO: These includes are for mitigating the pains of users editing their
|
|
||||||
// source because they relied on flatbuffers.h to include everything for them.
|
|
||||||
#include "flatbuffers/array.h"
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/buffer.h"
|
|
||||||
#include "flatbuffers/buffer_ref.h"
|
|
||||||
#include "flatbuffers/detached_buffer.h"
|
|
||||||
#include "flatbuffers/flatbuffer_builder.h"
|
|
||||||
#include "flatbuffers/stl_emulation.h"
|
|
||||||
#include "flatbuffers/string.h"
|
|
||||||
#include "flatbuffers/struct.h"
|
|
||||||
#include "flatbuffers/table.h"
|
|
||||||
#include "flatbuffers/vector.h"
|
|
||||||
#include "flatbuffers/vector_downward.h"
|
|
||||||
#include "flatbuffers/verifier.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
|
|
||||||
/// it is the opposite transformation of GetRoot().
|
|
||||||
/// This may be useful if you want to pass on a root and have the recipient
|
|
||||||
/// delete the buffer afterwards.
|
|
||||||
inline const uint8_t* GetBufferStartFromRootPointer(const void* root) {
|
|
||||||
auto table = reinterpret_cast<const Table*>(root);
|
|
||||||
auto vtable = table->GetVTable();
|
|
||||||
// Either the vtable is before the root or after the root.
|
|
||||||
auto start = (std::min)(vtable, reinterpret_cast<const uint8_t*>(root));
|
|
||||||
// Align to at least sizeof(uoffset_t).
|
|
||||||
start = reinterpret_cast<const uint8_t*>(reinterpret_cast<uintptr_t>(start) &
|
|
||||||
~(sizeof(uoffset_t) - 1));
|
|
||||||
// Additionally, there may be a file_identifier in the buffer, and the root
|
|
||||||
// offset. The buffer may have been aligned to any size between
|
|
||||||
// sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
|
|
||||||
// Sadly, the exact alignment is only known when constructing the buffer,
|
|
||||||
// since it depends on the presence of values with said alignment properties.
|
|
||||||
// So instead, we simply look at the next uoffset_t values (root,
|
|
||||||
// file_identifier, and alignment padding) to see which points to the root.
|
|
||||||
// None of the other values can "impersonate" the root since they will either
|
|
||||||
// be 0 or four ASCII characters.
|
|
||||||
static_assert(flatbuffers::kFileIdentifierLength == sizeof(uoffset_t),
|
|
||||||
"file_identifier is assumed to be the same size as uoffset_t");
|
|
||||||
for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
|
|
||||||
possible_roots; possible_roots--) {
|
|
||||||
start -= sizeof(uoffset_t);
|
|
||||||
if (ReadScalar<uoffset_t>(start) + start ==
|
|
||||||
reinterpret_cast<const uint8_t*>(root))
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
// We didn't find the root, either the "root" passed isn't really a root,
|
|
||||||
// or the buffer is corrupt.
|
|
||||||
// Assert, because calling this function with bad data may cause reads
|
|
||||||
// outside of buffer boundaries.
|
|
||||||
FLATBUFFERS_ASSERT(false);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief This return the prefixed size of a FlatBuffer.
|
|
||||||
template <typename SizeT = uoffset_t>
|
|
||||||
inline SizeT GetPrefixedSize(const uint8_t* buf) {
|
|
||||||
return ReadScalar<SizeT>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the total length of the buffer given a sized prefixed FlatBuffer.
|
|
||||||
//
|
|
||||||
// This includes the size of the prefix as well as the buffer:
|
|
||||||
//
|
|
||||||
// [size prefix][flatbuffer]
|
|
||||||
// |---------length--------|
|
|
||||||
template <typename SizeT = uoffset_t>
|
|
||||||
inline SizeT GetSizePrefixedBufferLength(const uint8_t* const buf) {
|
|
||||||
return ReadScalar<SizeT>(buf) + sizeof(SizeT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base class for native objects (FlatBuffer data de-serialized into native
|
|
||||||
// C++ data structures).
|
|
||||||
// Contains no functionality, purely documentative.
|
|
||||||
struct NativeTable {};
|
|
||||||
|
|
||||||
/// @brief Function types to be used with resolving hashes into objects and
|
|
||||||
/// back again. The resolver gets a pointer to a field inside an object API
|
|
||||||
/// object that is of the type specified in the schema using the attribute
|
|
||||||
/// `cpp_type` (it is thus important whatever you write to this address
|
|
||||||
/// matches that type). The value of this field is initially null, so you
|
|
||||||
/// may choose to implement a delayed binding lookup using this function
|
|
||||||
/// if you wish. The resolver does the opposite lookup, for when the object
|
|
||||||
/// is being serialized again.
|
|
||||||
typedef uint64_t hash_value_t;
|
|
||||||
typedef std::function<void(void** pointer_adr, hash_value_t hash)>
|
|
||||||
resolver_function_t;
|
|
||||||
typedef std::function<hash_value_t(void* pointer)> rehasher_function_t;
|
|
||||||
|
|
||||||
// Helper function to test if a field is present, using any of the field
|
|
||||||
// enums in the generated code.
|
|
||||||
// `table` must be a generated table type. Since this is a template parameter,
|
|
||||||
// this is not typechecked to be a subclass of Table, so beware!
|
|
||||||
// Note: this function will return false for fields equal to the default
|
|
||||||
// value, since they're not stored in the buffer (unless force_defaults was
|
|
||||||
// used).
|
|
||||||
template <typename T>
|
|
||||||
bool IsFieldPresent(const T* table, typename T::FlatBuffersVTableOffset field) {
|
|
||||||
// Cast, since Table is a private baseclass of any table types.
|
|
||||||
return reinterpret_cast<const Table*>(table)->CheckField(
|
|
||||||
static_cast<voffset_t>(field));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility function for reverse lookups on the EnumNames*() functions
|
|
||||||
// (in the generated C++ code)
|
|
||||||
// names must be NULL terminated.
|
|
||||||
inline int LookupEnum(const char** names, const char* name) {
|
|
||||||
for (const char** p = names; *p; p++)
|
|
||||||
if (!strcmp(*p, name)) return static_cast<int>(p - names);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These macros allow us to layout a struct with a guarantee that they'll end
|
|
||||||
// up looking the same on different compilers and platforms.
|
|
||||||
// It does this by disallowing the compiler to do any padding, and then
|
|
||||||
// does padding itself by inserting extra padding fields that make every
|
|
||||||
// element aligned to its own size.
|
|
||||||
// Additionally, it manually sets the alignment of the struct as a whole,
|
|
||||||
// which is typically its largest element, or a custom size set in the schema
|
|
||||||
// by the force_align attribute.
|
|
||||||
// These are used in the generated code only.
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
|
|
||||||
__pragma(pack(1)) \
|
|
||||||
struct __declspec(align(alignment))
|
|
||||||
#define FLATBUFFERS_STRUCT_END(name, size) \
|
|
||||||
__pragma(pack()) \
|
|
||||||
static_assert(sizeof(name) == size, "compiler breaks packing rules")
|
|
||||||
#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
|
|
||||||
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
|
|
||||||
_Pragma("pack(1)") \
|
|
||||||
struct __attribute__((aligned(alignment)))
|
|
||||||
#define FLATBUFFERS_STRUCT_END(name, size) \
|
|
||||||
_Pragma("pack()") \
|
|
||||||
static_assert(sizeof(name) == size, "compiler breaks packing rules")
|
|
||||||
#else
|
|
||||||
#error Unknown compiler, please define structure alignment macros
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
// Minimal reflection via code generation.
|
|
||||||
// Besides full-fat reflection (see reflection.h) and parsing/printing by
|
|
||||||
// loading schemas (see idl.h), we can also have code generation for minimal
|
|
||||||
// reflection data which allows pretty-printing and other uses without needing
|
|
||||||
// a schema or a parser.
|
|
||||||
// Generate code with --reflect-types (types only) or --reflect-names (names
|
|
||||||
// also) to enable.
|
|
||||||
// See minireflect.h for utilities using this functionality.
|
|
||||||
|
|
||||||
// These types are organized slightly differently as the ones in idl.h.
|
|
||||||
enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
|
|
||||||
|
|
||||||
// Scalars have the same order as in idl.h
|
|
||||||
// clang-format off
|
|
||||||
#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
|
|
||||||
ET(ET_UTYPE) \
|
|
||||||
ET(ET_BOOL) \
|
|
||||||
ET(ET_CHAR) \
|
|
||||||
ET(ET_UCHAR) \
|
|
||||||
ET(ET_SHORT) \
|
|
||||||
ET(ET_USHORT) \
|
|
||||||
ET(ET_INT) \
|
|
||||||
ET(ET_UINT) \
|
|
||||||
ET(ET_LONG) \
|
|
||||||
ET(ET_ULONG) \
|
|
||||||
ET(ET_FLOAT) \
|
|
||||||
ET(ET_DOUBLE) \
|
|
||||||
ET(ET_STRING) \
|
|
||||||
ET(ET_SEQUENCE) // See SequenceType.
|
|
||||||
|
|
||||||
enum ElementaryType {
|
|
||||||
#define FLATBUFFERS_ET(E) E,
|
|
||||||
FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
|
|
||||||
#undef FLATBUFFERS_ET
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char * const *ElementaryTypeNames() {
|
|
||||||
static const char * const names[] = {
|
|
||||||
#define FLATBUFFERS_ET(E) #E,
|
|
||||||
FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
|
|
||||||
#undef FLATBUFFERS_ET
|
|
||||||
};
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
// Basic type info cost just 16bits per field!
|
|
||||||
// We're explicitly defining the signedness since the signedness of integer
|
|
||||||
// bitfields is otherwise implementation-defined and causes warnings on older
|
|
||||||
// GCC compilers.
|
|
||||||
struct TypeCode {
|
|
||||||
// ElementaryType
|
|
||||||
unsigned short base_type : 4;
|
|
||||||
// Either vector (in table) or array (in struct)
|
|
||||||
unsigned short is_repeating : 1;
|
|
||||||
// Index into type_refs below, or -1 for none.
|
|
||||||
signed short sequence_ref : 11;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(TypeCode) == 2, "TypeCode");
|
|
||||||
|
|
||||||
struct TypeTable;
|
|
||||||
|
|
||||||
// Signature of the static method present in each type.
|
|
||||||
typedef const TypeTable* (*TypeFunction)();
|
|
||||||
|
|
||||||
struct TypeTable {
|
|
||||||
SequenceType st;
|
|
||||||
size_t num_elems; // of type_codes, values, names (but not type_refs).
|
|
||||||
const TypeCode* type_codes; // num_elems count
|
|
||||||
const TypeFunction* type_refs; // less than num_elems entries (see TypeCode).
|
|
||||||
const int16_t* array_sizes; // less than num_elems entries (see TypeCode).
|
|
||||||
const int64_t* values; // Only set for non-consecutive enum/union or structs.
|
|
||||||
const char* const* names; // Only set if compiled with --reflect-names.
|
|
||||||
};
|
|
||||||
|
|
||||||
// String which identifies the current version of FlatBuffers.
|
|
||||||
inline const char* flatbuffers_version_string() {
|
|
||||||
return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
|
|
||||||
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
|
|
||||||
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
|
|
||||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator | (E lhs, E rhs){\
|
|
||||||
return E(T(lhs) | T(rhs));\
|
|
||||||
}\
|
|
||||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator & (E lhs, E rhs){\
|
|
||||||
return E(T(lhs) & T(rhs));\
|
|
||||||
}\
|
|
||||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator ^ (E lhs, E rhs){\
|
|
||||||
return E(T(lhs) ^ T(rhs));\
|
|
||||||
}\
|
|
||||||
inline FLATBUFFERS_CONSTEXPR_CPP11 E operator ~ (E lhs){\
|
|
||||||
return E(~T(lhs));\
|
|
||||||
}\
|
|
||||||
inline FLATBUFFERS_CONSTEXPR_CPP14 E operator |= (E &lhs, E rhs){\
|
|
||||||
lhs = lhs | rhs;\
|
|
||||||
return lhs;\
|
|
||||||
}\
|
|
||||||
inline FLATBUFFERS_CONSTEXPR_CPP14 E operator &= (E &lhs, E rhs){\
|
|
||||||
lhs = lhs & rhs;\
|
|
||||||
return lhs;\
|
|
||||||
}\
|
|
||||||
inline FLATBUFFERS_CONSTEXPR_CPP14 E operator ^= (E &lhs, E rhs){\
|
|
||||||
lhs = lhs ^ rhs;\
|
|
||||||
return lhs;\
|
|
||||||
}\
|
|
||||||
inline FLATBUFFERS_CONSTEXPR_CPP11 bool operator !(E rhs) \
|
|
||||||
{\
|
|
||||||
return !bool(T(rhs)); \
|
|
||||||
}
|
|
||||||
/// @endcond
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_H_
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_FLATC_H_
|
|
||||||
#define FLATBUFFERS_FLATC_H_
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <limits>
|
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "flatbuffers/code_generator.h"
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "flatbuffers/idl.h"
|
|
||||||
#include "flatbuffers/util.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
extern void LogCompilerWarn(const std::string& warn);
|
|
||||||
extern void LogCompilerError(const std::string& err);
|
|
||||||
|
|
||||||
struct FlatCOptions {
|
|
||||||
IDLOptions opts;
|
|
||||||
|
|
||||||
std::string program_name;
|
|
||||||
|
|
||||||
std::string output_path;
|
|
||||||
|
|
||||||
std::vector<std::string> filenames;
|
|
||||||
|
|
||||||
std::list<std::string> include_directories_storage;
|
|
||||||
std::vector<const char*> include_directories;
|
|
||||||
std::vector<const char*> conform_include_directories;
|
|
||||||
std::vector<bool> generator_enabled;
|
|
||||||
size_t binary_files_from = std::numeric_limits<size_t>::max();
|
|
||||||
std::string conform_to_schema;
|
|
||||||
std::string annotate_schema;
|
|
||||||
bool annotate_include_vector_contents = true;
|
|
||||||
bool any_generator = false;
|
|
||||||
bool print_make_rules = false;
|
|
||||||
bool raw_binary = false;
|
|
||||||
bool schema_binary = false;
|
|
||||||
bool grpc_enabled = false;
|
|
||||||
bool requires_bfbs = false;
|
|
||||||
bool file_names_only = false;
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<CodeGenerator>> generators;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FlatCOption {
|
|
||||||
std::string short_opt;
|
|
||||||
std::string long_opt;
|
|
||||||
std::string parameter;
|
|
||||||
std::string description;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FlatCompiler {
|
|
||||||
public:
|
|
||||||
typedef void (*WarnFn)(const FlatCompiler* flatc, const std::string& warn,
|
|
||||||
bool show_exe_name);
|
|
||||||
|
|
||||||
typedef void (*ErrorFn)(const FlatCompiler* flatc, const std::string& err,
|
|
||||||
bool usage, bool show_exe_name);
|
|
||||||
|
|
||||||
// Parameters required to initialize the FlatCompiler.
|
|
||||||
struct InitParams {
|
|
||||||
InitParams() : warn_fn(nullptr), error_fn(nullptr) {}
|
|
||||||
|
|
||||||
WarnFn warn_fn;
|
|
||||||
ErrorFn error_fn;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit FlatCompiler(const InitParams& params) : params_(params) {}
|
|
||||||
|
|
||||||
bool RegisterCodeGenerator(const FlatCOption& option,
|
|
||||||
std::shared_ptr<CodeGenerator> code_generator);
|
|
||||||
|
|
||||||
int Compile(const FlatCOptions& options);
|
|
||||||
|
|
||||||
std::string GetShortUsageString(const std::string& program_name) const;
|
|
||||||
std::string GetUsageString(const std::string& program_name) const;
|
|
||||||
|
|
||||||
// Parse the FlatC options from command line arguments.
|
|
||||||
FlatCOptions ParseFromCommandLineArguments(int argc, const char** argv);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ParseFile(flatbuffers::Parser& parser, const std::string& filename,
|
|
||||||
const std::string& contents,
|
|
||||||
const std::vector<const char*>& include_directories) const;
|
|
||||||
|
|
||||||
void LoadBinarySchema(Parser& parser, const std::string& filename,
|
|
||||||
const std::string& contents);
|
|
||||||
|
|
||||||
void Warn(const std::string& warn, bool show_exe_name = true) const;
|
|
||||||
|
|
||||||
void Error(const std::string& err, bool usage = true,
|
|
||||||
bool show_exe_name = true) const;
|
|
||||||
|
|
||||||
void AnnotateBinaries(const uint8_t* binary_schema,
|
|
||||||
uint64_t binary_schema_size,
|
|
||||||
const FlatCOptions& options);
|
|
||||||
|
|
||||||
void ValidateOptions(const FlatCOptions& options);
|
|
||||||
|
|
||||||
Parser GetConformParser(const FlatCOptions& options);
|
|
||||||
|
|
||||||
std::unique_ptr<Parser> GenerateCode(const FlatCOptions& options,
|
|
||||||
Parser& conform_parser);
|
|
||||||
|
|
||||||
std::map<std::string, std::shared_ptr<CodeGenerator>> code_generators_;
|
|
||||||
|
|
||||||
InitParams params_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_FLATC_H_
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_FLEX_FLAT_UTIL_H_
|
|
||||||
#define FLATBUFFERS_FLEX_FLAT_UTIL_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "flatbuffers/flexbuffers.h"
|
|
||||||
|
|
||||||
namespace flexbuffers {
|
|
||||||
|
|
||||||
// Verifies the `nested` flexbuffer within a flatbuffer vector is valid.
|
|
||||||
template <bool B>
|
|
||||||
inline bool VerifyNestedFlexBuffer(
|
|
||||||
const flatbuffers::Vector<uint8_t>* const nested,
|
|
||||||
flatbuffers::VerifierTemplate<B>& verifier) {
|
|
||||||
if (!nested) return true;
|
|
||||||
return verifier.Check(flexbuffers::VerifyBuffer(
|
|
||||||
nested->data(), nested->size(), verifier.GetFlexReuseTracker()));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flexbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_FLEX_FLAT_UTIL_H_
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,303 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GRPC_H_
|
|
||||||
#define FLATBUFFERS_GRPC_H_
|
|
||||||
|
|
||||||
// Helper functionality to glue FlatBuffers and GRPC.
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "grpcpp/support/byte_buffer.h"
|
|
||||||
#include "grpcpp/support/slice.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
namespace grpc {
|
|
||||||
|
|
||||||
// Message is a typed wrapper around a buffer that manages the underlying
|
|
||||||
// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
|
|
||||||
// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
|
|
||||||
// is refcounted and ownership is be managed automatically.
|
|
||||||
template <class T>
|
|
||||||
class Message {
|
|
||||||
public:
|
|
||||||
Message() {}
|
|
||||||
|
|
||||||
Message(::grpc::Slice slice) : slice_(slice) {}
|
|
||||||
|
|
||||||
Message& operator=(const Message& other) = delete;
|
|
||||||
|
|
||||||
Message(Message&& other) = default;
|
|
||||||
|
|
||||||
Message(const Message& other) = delete;
|
|
||||||
|
|
||||||
Message& operator=(Message&& other) = default;
|
|
||||||
|
|
||||||
const uint8_t* mutable_data() const { return slice_.begin(); }
|
|
||||||
|
|
||||||
const uint8_t* data() const { return slice_.begin(); }
|
|
||||||
|
|
||||||
size_t size() const { return slice_.size(); }
|
|
||||||
|
|
||||||
bool Verify() const {
|
|
||||||
Verifier verifier(data(), size());
|
|
||||||
return verifier.VerifyBuffer<T>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
T* GetMutableRoot() { return flatbuffers::GetMutableRoot<T>(mutable_data()); }
|
|
||||||
|
|
||||||
const T* GetRoot() const { return flatbuffers::GetRoot<T>(data()); }
|
|
||||||
|
|
||||||
// This is only intended for serializer use, or if you know what you're doing
|
|
||||||
const ::grpc::Slice& BorrowSlice() const { return slice_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
::grpc::Slice slice_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MessageBuilder;
|
|
||||||
|
|
||||||
// SliceAllocator is a gRPC-specific allocator that uses the `grpc_slice`
|
|
||||||
// refcounted slices to manage memory ownership. This makes it easy and
|
|
||||||
// efficient to transfer buffers to gRPC.
|
|
||||||
class SliceAllocator : public Allocator {
|
|
||||||
public:
|
|
||||||
SliceAllocator() {}
|
|
||||||
|
|
||||||
SliceAllocator(const SliceAllocator& other) = delete;
|
|
||||||
SliceAllocator& operator=(const SliceAllocator& other) = delete;
|
|
||||||
|
|
||||||
SliceAllocator(SliceAllocator&& other) {
|
|
||||||
// default-construct and swap idiom
|
|
||||||
swap(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
SliceAllocator& operator=(SliceAllocator&& other) {
|
|
||||||
// move-construct and swap idiom
|
|
||||||
SliceAllocator temp(std::move(other));
|
|
||||||
swap(temp);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(SliceAllocator& other) {
|
|
||||||
using std::swap;
|
|
||||||
swap(slice_, other.slice_);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~SliceAllocator() {}
|
|
||||||
|
|
||||||
virtual uint8_t* allocate(size_t size) override {
|
|
||||||
FLATBUFFERS_ASSERT(slice_.size() == 0);
|
|
||||||
slice_ = ::grpc::Slice(size);
|
|
||||||
return const_cast<uint8_t*>(slice_.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void deallocate(uint8_t* p, size_t size) override {
|
|
||||||
FLATBUFFERS_ASSERT(p == slice_.begin());
|
|
||||||
FLATBUFFERS_ASSERT(size == slice_.size());
|
|
||||||
slice_ = ::grpc::Slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint8_t* reallocate_downward(uint8_t* old_p, size_t old_size,
|
|
||||||
size_t new_size, size_t in_use_back,
|
|
||||||
size_t in_use_front) override {
|
|
||||||
FLATBUFFERS_ASSERT(old_p == slice_.begin());
|
|
||||||
FLATBUFFERS_ASSERT(old_size == slice_.size());
|
|
||||||
FLATBUFFERS_ASSERT(new_size > old_size);
|
|
||||||
::grpc::Slice old_slice = slice_;
|
|
||||||
::grpc::Slice new_slice = ::grpc::Slice(new_size);
|
|
||||||
uint8_t* new_p = const_cast<uint8_t*>(new_slice.begin());
|
|
||||||
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
|
|
||||||
in_use_front);
|
|
||||||
slice_ = new_slice;
|
|
||||||
return const_cast<uint8_t*>(slice_.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
::grpc::Slice& get_slice(uint8_t* p, size_t size) {
|
|
||||||
FLATBUFFERS_ASSERT(p == slice_.begin());
|
|
||||||
FLATBUFFERS_ASSERT(size == slice_.size());
|
|
||||||
return slice_;
|
|
||||||
}
|
|
||||||
|
|
||||||
::grpc::Slice slice_;
|
|
||||||
|
|
||||||
friend class MessageBuilder;
|
|
||||||
};
|
|
||||||
|
|
||||||
// SliceAllocatorMember is a hack to ensure that the MessageBuilder's
|
|
||||||
// slice_allocator_ member is constructed before the FlatBufferBuilder, since
|
|
||||||
// the allocator is used in the FlatBufferBuilder ctor.
|
|
||||||
namespace detail {
|
|
||||||
struct SliceAllocatorMember {
|
|
||||||
SliceAllocator slice_allocator_;
|
|
||||||
};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
|
|
||||||
// to allocate gRPC buffers.
|
|
||||||
class MessageBuilder : private detail::SliceAllocatorMember,
|
|
||||||
public FlatBufferBuilder {
|
|
||||||
public:
|
|
||||||
explicit MessageBuilder(uoffset_t initial_size = 1024)
|
|
||||||
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
|
|
||||||
|
|
||||||
MessageBuilder(const MessageBuilder& other) = delete;
|
|
||||||
MessageBuilder& operator=(const MessageBuilder& other) = delete;
|
|
||||||
|
|
||||||
MessageBuilder(MessageBuilder&& other)
|
|
||||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
|
||||||
// Default construct and swap idiom.
|
|
||||||
Swap(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a MessageBuilder from a FlatBufferBuilder.
|
|
||||||
explicit MessageBuilder(FlatBufferBuilder&& src,
|
|
||||||
void (*dealloc)(void*,
|
|
||||||
size_t) = &DefaultAllocator::dealloc)
|
|
||||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
|
||||||
src.Swap(*this);
|
|
||||||
src.SwapBufAllocator(*this);
|
|
||||||
if (buf_.capacity()) {
|
|
||||||
uint8_t* buf = buf_.scratch_data(); // pointer to memory
|
|
||||||
size_t capacity = buf_.capacity(); // size of memory
|
|
||||||
slice_allocator_.slice_ = ::grpc::Slice(buf, capacity, dealloc);
|
|
||||||
} else {
|
|
||||||
slice_allocator_.slice_ = ::grpc::Slice();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Move-assign a FlatBufferBuilder to a MessageBuilder.
|
|
||||||
/// Only FlatBufferBuilder with default allocator (basically, nullptr) is
|
|
||||||
/// supported.
|
|
||||||
MessageBuilder& operator=(FlatBufferBuilder&& src) {
|
|
||||||
// Move construct a temporary and swap
|
|
||||||
MessageBuilder temp(std::move(src));
|
|
||||||
Swap(temp);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageBuilder& operator=(MessageBuilder&& other) {
|
|
||||||
// Move construct a temporary and swap
|
|
||||||
MessageBuilder temp(std::move(other));
|
|
||||||
Swap(temp);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Swap(MessageBuilder& other) {
|
|
||||||
slice_allocator_.swap(other.slice_allocator_);
|
|
||||||
FlatBufferBuilder::Swap(other);
|
|
||||||
// After swapping the FlatBufferBuilder, we swap back the allocator, which
|
|
||||||
// restores the original allocator back in place. This is necessary because
|
|
||||||
// MessageBuilder's allocator is its own member (SliceAllocatorMember). The
|
|
||||||
// allocator passed to FlatBufferBuilder::vector_downward must point to this
|
|
||||||
// member.
|
|
||||||
buf_.swap_allocator(other.buf_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Releases the ownership of the buffer pointer.
|
|
||||||
// Returns the size, offset, and the original grpc_slice that
|
|
||||||
// allocated the buffer. Also see grpc_slice_unref().
|
|
||||||
uint8_t* ReleaseRaw(size_t& size, size_t& offset, ::grpc::Slice& slice) {
|
|
||||||
uint8_t* buf = FlatBufferBuilder::ReleaseRaw(size, offset);
|
|
||||||
slice = slice_allocator_.slice_;
|
|
||||||
slice_allocator_.slice_ = ::grpc::Slice();
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
~MessageBuilder() {}
|
|
||||||
|
|
||||||
// GetMessage extracts the subslice of the buffer corresponding to the
|
|
||||||
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
|
|
||||||
// ownership.
|
|
||||||
template <class T>
|
|
||||||
Message<T> GetMessage() {
|
|
||||||
auto buf_data = buf_.scratch_data(); // pointer to memory
|
|
||||||
auto buf_size = buf_.capacity(); // size of memory
|
|
||||||
auto msg_data = buf_.data(); // pointer to msg
|
|
||||||
auto msg_size = buf_.size(); // size of msg
|
|
||||||
// Do some sanity checks on data/size
|
|
||||||
FLATBUFFERS_ASSERT(msg_data);
|
|
||||||
FLATBUFFERS_ASSERT(msg_size);
|
|
||||||
FLATBUFFERS_ASSERT(msg_data >= buf_data);
|
|
||||||
FLATBUFFERS_ASSERT(msg_data + msg_size <= buf_data + buf_size);
|
|
||||||
// Calculate offsets from the buffer start
|
|
||||||
auto begin = msg_data - buf_data;
|
|
||||||
auto end = begin + msg_size;
|
|
||||||
// Get the slice we are working with (no refcount change)
|
|
||||||
::grpc::Slice slice = slice_allocator_.get_slice(buf_data, buf_size);
|
|
||||||
// Extract a subslice of the existing slice (increment refcount)
|
|
||||||
::grpc::Slice subslice = slice.sub(begin, end);
|
|
||||||
// Wrap the subslice in a `Message<T>`, but don't increment refcount
|
|
||||||
Message<T> msg(subslice);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Message<T> ReleaseMessage() {
|
|
||||||
Message<T> msg = GetMessage<T>();
|
|
||||||
Reset();
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// SliceAllocator slice_allocator_; // part of SliceAllocatorMember
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace grpc
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
namespace grpc {
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
|
||||||
public:
|
|
||||||
static grpc::Status Serialize(const flatbuffers::grpc::Message<T>& msg,
|
|
||||||
ByteBuffer* buffer, bool* own_buffer) {
|
|
||||||
// Package the single slice into a `ByteBuffer`,
|
|
||||||
// incrementing the refcount in the process.
|
|
||||||
*buffer = ByteBuffer(&msg.BorrowSlice(), 1);
|
|
||||||
*own_buffer = true;
|
|
||||||
return grpc::Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize by pulling the
|
|
||||||
static grpc::Status Deserialize(ByteBuffer* buf,
|
|
||||||
flatbuffers::grpc::Message<T>* msg) {
|
|
||||||
Slice slice;
|
|
||||||
if (!buf->TrySingleSlice(&slice).ok()) {
|
|
||||||
if (!buf->DumpToSingleSlice(&slice).ok()) {
|
|
||||||
buf->Clear();
|
|
||||||
return ::grpc::Status(::grpc::StatusCode::INTERNAL, "No payload");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*msg = flatbuffers::grpc::Message<T>(slice);
|
|
||||||
buf->Clear();
|
|
||||||
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
|
||||||
return ::grpc::Status::OK;
|
|
||||||
#else
|
|
||||||
if (msg->Verify()) {
|
|
||||||
return ::grpc::Status::OK;
|
|
||||||
} else {
|
|
||||||
return ::grpc::Status(::grpc::StatusCode::INTERNAL,
|
|
||||||
"Message verification failed");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace grpc
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_GRPC_H_
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_HASH_H_
|
|
||||||
#define FLATBUFFERS_HASH_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct FnvTraits {
|
|
||||||
static const T kFnvPrime;
|
|
||||||
static const T kOffsetBasis;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FnvTraits<uint32_t> {
|
|
||||||
static const uint32_t kFnvPrime = 0x01000193;
|
|
||||||
static const uint32_t kOffsetBasis = 0x811C9DC5;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FnvTraits<uint64_t> {
|
|
||||||
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
|
|
||||||
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T HashFnv1(const char* input) {
|
|
||||||
T hash = FnvTraits<T>::kOffsetBasis;
|
|
||||||
for (const char* c = input; *c; ++c) {
|
|
||||||
hash *= FnvTraits<T>::kFnvPrime;
|
|
||||||
hash ^= static_cast<unsigned char>(*c);
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T HashFnv1a(const char* input) {
|
|
||||||
T hash = FnvTraits<T>::kOffsetBasis;
|
|
||||||
for (const char* c = input; *c; ++c) {
|
|
||||||
hash ^= static_cast<unsigned char>(*c);
|
|
||||||
hash *= FnvTraits<T>::kFnvPrime;
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline uint16_t HashFnv1<uint16_t>(const char* input) {
|
|
||||||
uint32_t hash = HashFnv1<uint32_t>(input);
|
|
||||||
return (hash >> 16) ^ (hash & 0xffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline uint16_t HashFnv1a<uint16_t>(const char* input) {
|
|
||||||
uint32_t hash = HashFnv1a<uint32_t>(input);
|
|
||||||
return (hash >> 16) ^ (hash & 0xffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct NamedHashFunction {
|
|
||||||
const char* name;
|
|
||||||
|
|
||||||
typedef T (*HashFunction)(const char*);
|
|
||||||
HashFunction function;
|
|
||||||
};
|
|
||||||
|
|
||||||
const NamedHashFunction<uint16_t> kHashFunctions16[] = {
|
|
||||||
{"fnv1_16", HashFnv1<uint16_t>},
|
|
||||||
{"fnv1a_16", HashFnv1a<uint16_t>},
|
|
||||||
};
|
|
||||||
|
|
||||||
const NamedHashFunction<uint32_t> kHashFunctions32[] = {
|
|
||||||
{"fnv1_32", HashFnv1<uint32_t>},
|
|
||||||
{"fnv1a_32", HashFnv1a<uint32_t>},
|
|
||||||
};
|
|
||||||
|
|
||||||
const NamedHashFunction<uint64_t> kHashFunctions64[] = {
|
|
||||||
{"fnv1_64", HashFnv1<uint64_t>},
|
|
||||||
{"fnv1a_64", HashFnv1a<uint64_t>},
|
|
||||||
};
|
|
||||||
|
|
||||||
inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16(
|
|
||||||
const char* name) {
|
|
||||||
std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]);
|
|
||||||
for (std::size_t i = 0; i < size; ++i) {
|
|
||||||
if (std::strcmp(name, kHashFunctions16[i].name) == 0) {
|
|
||||||
return kHashFunctions16[i].function;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(
|
|
||||||
const char* name) {
|
|
||||||
std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);
|
|
||||||
for (std::size_t i = 0; i < size; ++i) {
|
|
||||||
if (std::strcmp(name, kHashFunctions32[i].name) == 0) {
|
|
||||||
return kHashFunctions32[i].function;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NamedHashFunction<uint64_t>::HashFunction FindHashFunction64(
|
|
||||||
const char* name) {
|
|
||||||
std::size_t size = sizeof(kHashFunctions64) / sizeof(kHashFunctions64[0]);
|
|
||||||
for (std::size_t i = 0; i < size; ++i) {
|
|
||||||
if (std::strcmp(name, kHashFunctions64[i].name) == 0) {
|
|
||||||
return kHashFunctions64[i].function;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_HASH_H_
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,441 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_MINIREFLECT_H_
|
|
||||||
#define FLATBUFFERS_MINIREFLECT_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "flatbuffers/util.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Utilities that can be used with the "mini reflection" tables present
|
|
||||||
// in generated code with --reflect-types (only types) or --reflect-names
|
|
||||||
// (also names).
|
|
||||||
// This allows basic reflection functionality such as pretty-printing
|
|
||||||
// that does not require the use of the schema parser or loading of binary
|
|
||||||
// schema files at runtime (reflection.h).
|
|
||||||
|
|
||||||
// For any of the functions below that take `const TypeTable *`, you pass
|
|
||||||
// `FooTypeTable()` if the type of the root is `Foo`.
|
|
||||||
|
|
||||||
// First, a generic iterator that can be used by multiple algorithms.
|
|
||||||
|
|
||||||
struct IterationVisitor {
|
|
||||||
// These mark the scope of a table or struct.
|
|
||||||
virtual void StartSequence() {}
|
|
||||||
virtual void EndSequence() {}
|
|
||||||
// Called for each field regardless of whether it is present or not.
|
|
||||||
// If not present, val == nullptr. set_idx is the index of all set fields.
|
|
||||||
virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/,
|
|
||||||
ElementaryType /*type*/, bool /*is_vector*/,
|
|
||||||
const TypeTable* /*type_table*/, const char* /*name*/,
|
|
||||||
const uint8_t* /*val*/) {}
|
|
||||||
// Called for a value that is actually present, after a field, or as part
|
|
||||||
// of a vector.
|
|
||||||
virtual void UType(uint8_t, const char*) {}
|
|
||||||
virtual void Bool(bool) {}
|
|
||||||
virtual void Char(int8_t, const char*) {}
|
|
||||||
virtual void UChar(uint8_t, const char*) {}
|
|
||||||
virtual void Short(int16_t, const char*) {}
|
|
||||||
virtual void UShort(uint16_t, const char*) {}
|
|
||||||
virtual void Int(int32_t, const char*) {}
|
|
||||||
virtual void UInt(uint32_t, const char*) {}
|
|
||||||
virtual void Long(int64_t) {}
|
|
||||||
virtual void ULong(uint64_t) {}
|
|
||||||
virtual void Float(float) {}
|
|
||||||
virtual void Double(double) {}
|
|
||||||
virtual void String(const String*) {}
|
|
||||||
virtual void Unknown(const uint8_t*) {} // From a future version.
|
|
||||||
// These mark the scope of a vector.
|
|
||||||
virtual void StartVector() {}
|
|
||||||
virtual void EndVector() {}
|
|
||||||
virtual void Element(size_t /*i*/, ElementaryType /*type*/,
|
|
||||||
const TypeTable* /*type_table*/,
|
|
||||||
const uint8_t* /*val*/) {}
|
|
||||||
virtual ~IterationVisitor() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline size_t InlineSize(ElementaryType type, const TypeTable* type_table) {
|
|
||||||
switch (type) {
|
|
||||||
case ET_UTYPE:
|
|
||||||
case ET_BOOL:
|
|
||||||
case ET_CHAR:
|
|
||||||
case ET_UCHAR:
|
|
||||||
return 1;
|
|
||||||
case ET_SHORT:
|
|
||||||
case ET_USHORT:
|
|
||||||
return 2;
|
|
||||||
case ET_INT:
|
|
||||||
case ET_UINT:
|
|
||||||
case ET_FLOAT:
|
|
||||||
case ET_STRING:
|
|
||||||
return 4;
|
|
||||||
case ET_LONG:
|
|
||||||
case ET_ULONG:
|
|
||||||
case ET_DOUBLE:
|
|
||||||
return 8;
|
|
||||||
case ET_SEQUENCE:
|
|
||||||
switch (type_table->st) {
|
|
||||||
case ST_TABLE:
|
|
||||||
case ST_UNION:
|
|
||||||
return 4;
|
|
||||||
case ST_STRUCT:
|
|
||||||
return static_cast<size_t>(type_table->values[type_table->num_elems]);
|
|
||||||
default:
|
|
||||||
FLATBUFFERS_ASSERT(false);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
FLATBUFFERS_ASSERT(false);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t LookupEnum(int64_t enum_val, const int64_t* values,
|
|
||||||
size_t num_values) {
|
|
||||||
if (!values) return enum_val;
|
|
||||||
for (size_t i = 0; i < num_values; i++) {
|
|
||||||
if (enum_val == values[i]) return static_cast<int64_t>(i);
|
|
||||||
}
|
|
||||||
return -1; // Unknown enum value.
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
const char* EnumName(T tval, const TypeTable* type_table) {
|
|
||||||
if (!type_table || !type_table->names) return nullptr;
|
|
||||||
auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values,
|
|
||||||
type_table->num_elems);
|
|
||||||
if (i >= 0 && i < static_cast<int64_t>(type_table->num_elems)) {
|
|
||||||
return type_table->names[i];
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IterateObject(const uint8_t* obj, const TypeTable* type_table,
|
|
||||||
IterationVisitor* visitor);
|
|
||||||
|
|
||||||
inline void IterateValue(ElementaryType type, const uint8_t* val,
|
|
||||||
const TypeTable* type_table, const uint8_t* prev_val,
|
|
||||||
soffset_t vector_index, IterationVisitor* visitor) {
|
|
||||||
switch (type) {
|
|
||||||
case ET_UTYPE: {
|
|
||||||
auto tval = ReadScalar<uint8_t>(val);
|
|
||||||
visitor->UType(tval, EnumName(tval, type_table));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_BOOL: {
|
|
||||||
visitor->Bool(ReadScalar<uint8_t>(val) != 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_CHAR: {
|
|
||||||
auto tval = ReadScalar<int8_t>(val);
|
|
||||||
visitor->Char(tval, EnumName(tval, type_table));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_UCHAR: {
|
|
||||||
auto tval = ReadScalar<uint8_t>(val);
|
|
||||||
visitor->UChar(tval, EnumName(tval, type_table));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_SHORT: {
|
|
||||||
auto tval = ReadScalar<int16_t>(val);
|
|
||||||
visitor->Short(tval, EnumName(tval, type_table));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_USHORT: {
|
|
||||||
auto tval = ReadScalar<uint16_t>(val);
|
|
||||||
visitor->UShort(tval, EnumName(tval, type_table));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_INT: {
|
|
||||||
auto tval = ReadScalar<int32_t>(val);
|
|
||||||
visitor->Int(tval, EnumName(tval, type_table));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_UINT: {
|
|
||||||
auto tval = ReadScalar<uint32_t>(val);
|
|
||||||
visitor->UInt(tval, EnumName(tval, type_table));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_LONG: {
|
|
||||||
visitor->Long(ReadScalar<int64_t>(val));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_ULONG: {
|
|
||||||
visitor->ULong(ReadScalar<uint64_t>(val));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_FLOAT: {
|
|
||||||
visitor->Float(ReadScalar<float>(val));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_DOUBLE: {
|
|
||||||
visitor->Double(ReadScalar<double>(val));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_STRING: {
|
|
||||||
val += ReadScalar<uoffset_t>(val);
|
|
||||||
visitor->String(reinterpret_cast<const String*>(val));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_SEQUENCE: {
|
|
||||||
switch (type_table->st) {
|
|
||||||
case ST_TABLE:
|
|
||||||
val += ReadScalar<uoffset_t>(val);
|
|
||||||
IterateObject(val, type_table, visitor);
|
|
||||||
break;
|
|
||||||
case ST_STRUCT:
|
|
||||||
IterateObject(val, type_table, visitor);
|
|
||||||
break;
|
|
||||||
case ST_UNION: {
|
|
||||||
val += ReadScalar<uoffset_t>(val);
|
|
||||||
FLATBUFFERS_ASSERT(prev_val);
|
|
||||||
auto union_type = *prev_val; // Always a uint8_t.
|
|
||||||
if (vector_index >= 0) {
|
|
||||||
auto type_vec = reinterpret_cast<const Vector<uint8_t>*>(prev_val);
|
|
||||||
union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
|
|
||||||
}
|
|
||||||
auto type_code_idx =
|
|
||||||
LookupEnum(union_type, type_table->values, type_table->num_elems);
|
|
||||||
if (type_code_idx >= 0 &&
|
|
||||||
type_code_idx < static_cast<int32_t>(type_table->num_elems)) {
|
|
||||||
auto type_code = type_table->type_codes[type_code_idx];
|
|
||||||
switch (type_code.base_type) {
|
|
||||||
case ET_SEQUENCE: {
|
|
||||||
auto ref = type_table->type_refs[type_code.sequence_ref]();
|
|
||||||
IterateObject(val, ref, visitor);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ET_STRING:
|
|
||||||
visitor->String(reinterpret_cast<const String*>(val));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
visitor->Unknown(val);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
visitor->Unknown(val);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ST_ENUM:
|
|
||||||
FLATBUFFERS_ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
visitor->Unknown(val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void IterateObject(const uint8_t* obj, const TypeTable* type_table,
|
|
||||||
IterationVisitor* visitor) {
|
|
||||||
visitor->StartSequence();
|
|
||||||
const uint8_t* prev_val = nullptr;
|
|
||||||
size_t set_idx = 0;
|
|
||||||
size_t array_idx = 0;
|
|
||||||
for (size_t i = 0; i < type_table->num_elems; i++) {
|
|
||||||
auto type_code = type_table->type_codes[i];
|
|
||||||
auto type = static_cast<ElementaryType>(type_code.base_type);
|
|
||||||
auto is_repeating = type_code.is_repeating != 0;
|
|
||||||
auto ref_idx = type_code.sequence_ref;
|
|
||||||
const TypeTable* ref = nullptr;
|
|
||||||
if (ref_idx >= 0) {
|
|
||||||
ref = type_table->type_refs[ref_idx]();
|
|
||||||
}
|
|
||||||
auto name = type_table->names ? type_table->names[i] : nullptr;
|
|
||||||
const uint8_t* val = nullptr;
|
|
||||||
if (type_table->st == ST_TABLE) {
|
|
||||||
val = reinterpret_cast<const Table*>(obj)->GetAddressOf(
|
|
||||||
FieldIndexToOffset(static_cast<voffset_t>(i)));
|
|
||||||
} else {
|
|
||||||
val = obj + type_table->values[i];
|
|
||||||
}
|
|
||||||
visitor->Field(i, set_idx, type, is_repeating, ref, name, val);
|
|
||||||
if (val) {
|
|
||||||
set_idx++;
|
|
||||||
if (is_repeating) {
|
|
||||||
auto elem_ptr = val;
|
|
||||||
size_t size = 0;
|
|
||||||
if (type_table->st == ST_TABLE) {
|
|
||||||
// variable length vector
|
|
||||||
val += ReadScalar<uoffset_t>(val);
|
|
||||||
auto vec = reinterpret_cast<const Vector<uint8_t>*>(val);
|
|
||||||
elem_ptr = vec->Data();
|
|
||||||
size = vec->size();
|
|
||||||
} else {
|
|
||||||
// otherwise fixed size array
|
|
||||||
size = type_table->array_sizes[array_idx];
|
|
||||||
++array_idx;
|
|
||||||
}
|
|
||||||
visitor->StartVector();
|
|
||||||
for (size_t j = 0; j < size; j++) {
|
|
||||||
visitor->Element(j, type, ref, elem_ptr);
|
|
||||||
IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j),
|
|
||||||
visitor);
|
|
||||||
elem_ptr += InlineSize(type, ref);
|
|
||||||
}
|
|
||||||
visitor->EndVector();
|
|
||||||
} else {
|
|
||||||
IterateValue(type, val, ref, prev_val, -1, visitor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prev_val = val;
|
|
||||||
}
|
|
||||||
visitor->EndSequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void IterateFlatBuffer(const uint8_t* buffer,
|
|
||||||
const TypeTable* type_table,
|
|
||||||
IterationVisitor* callback) {
|
|
||||||
IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
|
|
||||||
// the output generated by idl_gen_text.cpp.
|
|
||||||
|
|
||||||
struct ToStringVisitor : public IterationVisitor {
|
|
||||||
std::string s;
|
|
||||||
std::string d;
|
|
||||||
bool q;
|
|
||||||
std::string in;
|
|
||||||
size_t indent_level;
|
|
||||||
bool vector_delimited;
|
|
||||||
ToStringVisitor(std::string delimiter, bool quotes, std::string indent,
|
|
||||||
bool vdelimited = true)
|
|
||||||
: d(delimiter),
|
|
||||||
q(quotes),
|
|
||||||
in(indent),
|
|
||||||
indent_level(0),
|
|
||||||
vector_delimited(vdelimited) {}
|
|
||||||
ToStringVisitor(std::string delimiter)
|
|
||||||
: d(delimiter),
|
|
||||||
q(false),
|
|
||||||
in(""),
|
|
||||||
indent_level(0),
|
|
||||||
vector_delimited(true) {}
|
|
||||||
|
|
||||||
void append_indent() {
|
|
||||||
for (size_t i = 0; i < indent_level; i++) {
|
|
||||||
s += in;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartSequence() {
|
|
||||||
s += "{";
|
|
||||||
s += d;
|
|
||||||
indent_level++;
|
|
||||||
}
|
|
||||||
void EndSequence() {
|
|
||||||
s += d;
|
|
||||||
indent_level--;
|
|
||||||
append_indent();
|
|
||||||
s += "}";
|
|
||||||
}
|
|
||||||
void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
|
|
||||||
bool /*is_vector*/, const TypeTable* /*type_table*/,
|
|
||||||
const char* name, const uint8_t* val) {
|
|
||||||
if (!val) return;
|
|
||||||
if (set_idx) {
|
|
||||||
s += ",";
|
|
||||||
s += d;
|
|
||||||
}
|
|
||||||
append_indent();
|
|
||||||
if (name) {
|
|
||||||
if (q) s += "\"";
|
|
||||||
s += name;
|
|
||||||
if (q) s += "\"";
|
|
||||||
s += ": ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
void Named(T x, const char* name) {
|
|
||||||
if (name) {
|
|
||||||
if (q) s += "\"";
|
|
||||||
s += name;
|
|
||||||
if (q) s += "\"";
|
|
||||||
} else {
|
|
||||||
s += NumToString(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void UType(uint8_t x, const char* name) { Named(x, name); }
|
|
||||||
void Bool(bool x) { s += x ? "true" : "false"; }
|
|
||||||
void Char(int8_t x, const char* name) { Named(x, name); }
|
|
||||||
void UChar(uint8_t x, const char* name) { Named(x, name); }
|
|
||||||
void Short(int16_t x, const char* name) { Named(x, name); }
|
|
||||||
void UShort(uint16_t x, const char* name) { Named(x, name); }
|
|
||||||
void Int(int32_t x, const char* name) { Named(x, name); }
|
|
||||||
void UInt(uint32_t x, const char* name) { Named(x, name); }
|
|
||||||
void Long(int64_t x) { s += NumToString(x); }
|
|
||||||
void ULong(uint64_t x) { s += NumToString(x); }
|
|
||||||
void Float(float x) { s += NumToString(x); }
|
|
||||||
void Double(double x) { s += NumToString(x); }
|
|
||||||
void String(const struct String* str) {
|
|
||||||
EscapeString(str->c_str(), str->size(), &s, true, false);
|
|
||||||
}
|
|
||||||
void Unknown(const uint8_t*) { s += "(?)"; }
|
|
||||||
void StartVector() {
|
|
||||||
s += "[";
|
|
||||||
if (vector_delimited) {
|
|
||||||
s += d;
|
|
||||||
indent_level++;
|
|
||||||
append_indent();
|
|
||||||
} else {
|
|
||||||
s += " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void EndVector() {
|
|
||||||
if (vector_delimited) {
|
|
||||||
s += d;
|
|
||||||
indent_level--;
|
|
||||||
append_indent();
|
|
||||||
} else {
|
|
||||||
s += " ";
|
|
||||||
}
|
|
||||||
s += "]";
|
|
||||||
}
|
|
||||||
void Element(size_t i, ElementaryType /*type*/,
|
|
||||||
const TypeTable* /*type_table*/, const uint8_t* /*val*/) {
|
|
||||||
if (i) {
|
|
||||||
s += ",";
|
|
||||||
if (vector_delimited) {
|
|
||||||
s += d;
|
|
||||||
append_indent();
|
|
||||||
} else {
|
|
||||||
s += " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::string FlatBufferToString(const uint8_t* buffer,
|
|
||||||
const TypeTable* type_table,
|
|
||||||
bool multi_line = false,
|
|
||||||
bool vector_delimited = true,
|
|
||||||
const std::string& indent = "",
|
|
||||||
bool quotes = false) {
|
|
||||||
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", quotes, indent,
|
|
||||||
vector_delimited);
|
|
||||||
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
|
|
||||||
return tostring_visitor.s;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_MINIREFLECT_H_
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_FLATC_PCH_H_
|
|
||||||
#define FLATBUFFERS_FLATC_PCH_H_
|
|
||||||
|
|
||||||
// stl
|
|
||||||
#include <cassert>
|
|
||||||
#include <cmath>
|
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <set>
|
|
||||||
#include <sstream>
|
|
||||||
#include <tuple>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
// flatbuffers
|
|
||||||
#include "flatbuffers/code_generators.h"
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "flatbuffers/flexbuffers.h"
|
|
||||||
#include "flatbuffers/idl.h"
|
|
||||||
#include "flatbuffers/pch/pch.h"
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_FLATC_PCH_H_
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_PCH_H_
|
|
||||||
#define FLATBUFFERS_PCH_H_
|
|
||||||
|
|
||||||
// stl
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <limits>
|
|
||||||
#include <list>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <stack>
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// flatbuffers
|
|
||||||
#include "flatbuffers/util.h"
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_PCH_H_
|
|
||||||
@@ -1,530 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_REFLECTION_H_
|
|
||||||
#define FLATBUFFERS_REFLECTION_H_
|
|
||||||
|
|
||||||
// This is somewhat of a circular dependency because flatc (and thus this
|
|
||||||
// file) is needed to generate this header in the first place.
|
|
||||||
// Should normally not be a problem since it can be generated by the
|
|
||||||
// previous version of flatc whenever this code needs to change.
|
|
||||||
// See scripts/generate_code.py for generation.
|
|
||||||
#include "flatbuffers/reflection_generated.h"
|
|
||||||
|
|
||||||
// Helper functionality for reflection.
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// ------------------------- GETTERS -------------------------
|
|
||||||
|
|
||||||
constexpr bool IsScalar(reflection::BaseType t) {
|
|
||||||
return t >= reflection::UType && t <= reflection::Double;
|
|
||||||
}
|
|
||||||
constexpr bool IsInteger(reflection::BaseType t) {
|
|
||||||
return t >= reflection::UType && t <= reflection::ULong;
|
|
||||||
}
|
|
||||||
constexpr bool IsFloat(reflection::BaseType t) {
|
|
||||||
return t == reflection::Float || t == reflection::Double;
|
|
||||||
}
|
|
||||||
constexpr bool IsLong(reflection::BaseType t) {
|
|
||||||
return t == reflection::Long || t == reflection::ULong;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This needs to correspond to the BaseType enum.
|
|
||||||
constexpr size_t kBaseTypeSize[] = {
|
|
||||||
0, // None
|
|
||||||
1, // UType
|
|
||||||
1, // Bool
|
|
||||||
1, // Byte
|
|
||||||
1, // UByte
|
|
||||||
2, // Short
|
|
||||||
2, // UShort
|
|
||||||
4, // Int
|
|
||||||
4, // UInt
|
|
||||||
8, // Long
|
|
||||||
8, // ULong
|
|
||||||
4, // Float
|
|
||||||
8, // Double
|
|
||||||
4, // String
|
|
||||||
4, // Vector
|
|
||||||
4, // Obj
|
|
||||||
4, // Union
|
|
||||||
0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds
|
|
||||||
// errors.
|
|
||||||
8, // Vector64
|
|
||||||
|
|
||||||
0 // MaxBaseType. This must be kept the last entry in this array.
|
|
||||||
};
|
|
||||||
static_assert(sizeof(kBaseTypeSize) / sizeof(size_t) ==
|
|
||||||
reflection::MaxBaseType + 1,
|
|
||||||
"Size of sizes[] array does not match the count of BaseType "
|
|
||||||
"enum values.");
|
|
||||||
|
|
||||||
// Size of a basic type, don't use with structs.
|
|
||||||
constexpr size_t GetTypeSize(reflection::BaseType base_type) {
|
|
||||||
return kBaseTypeSize[base_type];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same as above, but now correctly returns the size of a struct if
|
|
||||||
// the field (or vector element) is a struct.
|
|
||||||
inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
|
|
||||||
const reflection::Schema& schema) {
|
|
||||||
if (base_type == reflection::Obj &&
|
|
||||||
schema.objects()->Get(type_index)->is_struct()) {
|
|
||||||
return schema.objects()->Get(type_index)->bytesize();
|
|
||||||
} else {
|
|
||||||
return GetTypeSize(base_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the root, regardless of what type it is.
|
|
||||||
inline Table* GetAnyRoot(uint8_t* const flatbuf) {
|
|
||||||
return GetMutableRoot<Table>(flatbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Table* GetAnyRoot(const uint8_t* const flatbuf) {
|
|
||||||
return GetRoot<Table>(flatbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Table* GetAnySizePrefixedRoot(uint8_t* const flatbuf) {
|
|
||||||
return GetMutableSizePrefixedRoot<Table>(flatbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Table* GetAnySizePrefixedRoot(const uint8_t* const flatbuf) {
|
|
||||||
return GetSizePrefixedRoot<Table>(flatbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field's default, if you know it's an integer, and its exact type.
|
|
||||||
template <typename T>
|
|
||||||
T GetFieldDefaultI(const reflection::Field& field) {
|
|
||||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
|
||||||
return static_cast<T>(field.default_integer());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field's default, if you know it's floating point and its exact type.
|
|
||||||
template <typename T>
|
|
||||||
T GetFieldDefaultF(const reflection::Field& field) {
|
|
||||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
|
||||||
return static_cast<T>(field.default_real());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field, if you know it's an integer, and its exact type.
|
|
||||||
template <typename T>
|
|
||||||
T GetFieldI(const Table& table, const reflection::Field& field) {
|
|
||||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
|
||||||
return table.GetField<T>(field.offset(),
|
|
||||||
static_cast<T>(field.default_integer()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field, if you know it's floating point and its exact type.
|
|
||||||
template <typename T>
|
|
||||||
T GetFieldF(const Table& table, const reflection::Field& field) {
|
|
||||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
|
||||||
return table.GetField<T>(field.offset(),
|
|
||||||
static_cast<T>(field.default_real()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field, if you know it's a string.
|
|
||||||
inline const String* GetFieldS(const Table& table,
|
|
||||||
const reflection::Field& field) {
|
|
||||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String);
|
|
||||||
return table.GetPointer<const String*>(field.offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field, if you know it's a vector.
|
|
||||||
template <typename T>
|
|
||||||
Vector<T>* GetFieldV(const Table& table, const reflection::Field& field) {
|
|
||||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Vector &&
|
|
||||||
sizeof(T) == GetTypeSize(field.type()->element()));
|
|
||||||
return table.GetPointer<Vector<T>*>(field.offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field, if you know it's a vector, generically.
|
|
||||||
// To actually access elements, use the return value together with
|
|
||||||
// field.type()->element() in any of GetAnyVectorElemI below etc.
|
|
||||||
inline VectorOfAny* GetFieldAnyV(const Table& table,
|
|
||||||
const reflection::Field& field) {
|
|
||||||
return table.GetPointer<VectorOfAny*>(field.offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field, if you know it's a table.
|
|
||||||
inline Table* GetFieldT(const Table& table, const reflection::Field& field) {
|
|
||||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj ||
|
|
||||||
field.type()->base_type() == reflection::Union);
|
|
||||||
return table.GetPointer<Table*>(field.offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a field, if you know it's a struct.
|
|
||||||
inline const Struct* GetFieldStruct(const Table& table,
|
|
||||||
const reflection::Field& field) {
|
|
||||||
// TODO: This does NOT check if the field is a table or struct, but we'd need
|
|
||||||
// access to the schema to check the is_struct flag.
|
|
||||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
|
|
||||||
return table.GetStruct<const Struct*>(field.offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a structure's field, if you know it's a struct.
|
|
||||||
inline const Struct* GetFieldStruct(const Struct& structure,
|
|
||||||
const reflection::Field& field) {
|
|
||||||
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
|
|
||||||
return structure.GetStruct<const Struct*>(field.offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Raw helper functions used below: get any value in memory as a 64bit int, a
|
|
||||||
// double or a string.
|
|
||||||
// All scalars get static_cast to an int64_t, strings use strtoull, every other
|
|
||||||
// data type returns 0.
|
|
||||||
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t* data);
|
|
||||||
// All scalars static cast to double, strings use strtod, every other data
|
|
||||||
// type is 0.0.
|
|
||||||
double GetAnyValueF(reflection::BaseType type, const uint8_t* data);
|
|
||||||
// All scalars converted using stringstream, strings as-is, and all other
|
|
||||||
// data types provide some level of debug-pretty-printing.
|
|
||||||
std::string GetAnyValueS(reflection::BaseType type, const uint8_t* data,
|
|
||||||
const reflection::Schema* schema, int type_index);
|
|
||||||
|
|
||||||
// Get any table field as a 64bit int, regardless of what type it is.
|
|
||||||
inline int64_t GetAnyFieldI(const Table& table,
|
|
||||||
const reflection::Field& field) {
|
|
||||||
auto field_ptr = table.GetAddressOf(field.offset());
|
|
||||||
return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr)
|
|
||||||
: field.default_integer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get any table field as a double, regardless of what type it is.
|
|
||||||
inline double GetAnyFieldF(const Table& table, const reflection::Field& field) {
|
|
||||||
auto field_ptr = table.GetAddressOf(field.offset());
|
|
||||||
return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
|
|
||||||
: field.default_real();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get any table field as a string, regardless of what type it is.
|
|
||||||
// You may pass nullptr for the schema if you don't care to have fields that
|
|
||||||
// are of table type pretty-printed.
|
|
||||||
inline std::string GetAnyFieldS(const Table& table,
|
|
||||||
const reflection::Field& field,
|
|
||||||
const reflection::Schema* schema) {
|
|
||||||
auto field_ptr = table.GetAddressOf(field.offset());
|
|
||||||
return field_ptr ? GetAnyValueS(field.type()->base_type(), field_ptr, schema,
|
|
||||||
field.type()->index())
|
|
||||||
: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get any struct field as a 64bit int, regardless of what type it is.
|
|
||||||
inline int64_t GetAnyFieldI(const Struct& st, const reflection::Field& field) {
|
|
||||||
return GetAnyValueI(field.type()->base_type(),
|
|
||||||
st.GetAddressOf(field.offset()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get any struct field as a double, regardless of what type it is.
|
|
||||||
inline double GetAnyFieldF(const Struct& st, const reflection::Field& field) {
|
|
||||||
return GetAnyValueF(field.type()->base_type(),
|
|
||||||
st.GetAddressOf(field.offset()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get any struct field as a string, regardless of what type it is.
|
|
||||||
inline std::string GetAnyFieldS(const Struct& st,
|
|
||||||
const reflection::Field& field) {
|
|
||||||
return GetAnyValueS(field.type()->base_type(),
|
|
||||||
st.GetAddressOf(field.offset()), nullptr, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get any vector element as a 64bit int, regardless of what type it is.
|
|
||||||
inline int64_t GetAnyVectorElemI(const VectorOfAny* vec,
|
|
||||||
reflection::BaseType elem_type, size_t i) {
|
|
||||||
return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get any vector element as a double, regardless of what type it is.
|
|
||||||
inline double GetAnyVectorElemF(const VectorOfAny* vec,
|
|
||||||
reflection::BaseType elem_type, size_t i) {
|
|
||||||
return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get any vector element as a string, regardless of what type it is.
|
|
||||||
inline std::string GetAnyVectorElemS(const VectorOfAny* vec,
|
|
||||||
reflection::BaseType elem_type, size_t i) {
|
|
||||||
return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i,
|
|
||||||
nullptr, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a vector element that's a table/string/vector from a generic vector.
|
|
||||||
// Pass Table/String/VectorOfAny as template parameter.
|
|
||||||
// Warning: does no typechecking.
|
|
||||||
template <typename T>
|
|
||||||
T* GetAnyVectorElemPointer(const VectorOfAny* vec, size_t i) {
|
|
||||||
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
|
|
||||||
return reinterpret_cast<T*>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the inline-address of a vector element. Useful for Structs (pass Struct
|
|
||||||
// as template arg), or being able to address a range of scalars in-line.
|
|
||||||
// Get elem_size from GetTypeSizeInline().
|
|
||||||
// Note: little-endian data on all platforms, use EndianScalar() instead of
|
|
||||||
// raw pointer access with scalars).
|
|
||||||
template <typename T>
|
|
||||||
T* GetAnyVectorElemAddressOf(const VectorOfAny* vec, size_t i,
|
|
||||||
size_t elem_size) {
|
|
||||||
return reinterpret_cast<T*>(vec->Data() + elem_size * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Similarly, for elements of tables.
|
|
||||||
template <typename T>
|
|
||||||
T* GetAnyFieldAddressOf(const Table& table, const reflection::Field& field) {
|
|
||||||
return reinterpret_cast<T*>(table.GetAddressOf(field.offset()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Similarly, for elements of structs.
|
|
||||||
template <typename T>
|
|
||||||
T* GetAnyFieldAddressOf(const Struct& st, const reflection::Field& field) {
|
|
||||||
return reinterpret_cast<T*>(st.GetAddressOf(field.offset()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop over all the fields of the provided `object` and call `func` on each one
|
|
||||||
// in increasing order by their field->id(). If `reverse` is true, `func` is
|
|
||||||
// called in descending order
|
|
||||||
void ForAllFields(const reflection::Object* object, bool reverse,
|
|
||||||
std::function<void(const reflection::Field*)> func);
|
|
||||||
|
|
||||||
// ------------------------- SETTERS -------------------------
|
|
||||||
|
|
||||||
// Set any scalar field, if you know its exact type.
|
|
||||||
template <typename T>
|
|
||||||
bool SetField(Table* table, const reflection::Field& field, T val) {
|
|
||||||
reflection::BaseType type = field.type()->base_type();
|
|
||||||
if (!IsScalar(type)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type));
|
|
||||||
T def;
|
|
||||||
if (IsInteger(type)) {
|
|
||||||
def = GetFieldDefaultI<T>(field);
|
|
||||||
} else {
|
|
||||||
FLATBUFFERS_ASSERT(IsFloat(type));
|
|
||||||
def = GetFieldDefaultF<T>(field);
|
|
||||||
}
|
|
||||||
return table->SetField(field.offset(), val, def);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Raw helper functions used below: set any value in memory as a 64bit int, a
|
|
||||||
// double or a string.
|
|
||||||
// These work for all scalar values, but do nothing for other data types.
|
|
||||||
// To set a string, see SetString below.
|
|
||||||
void SetAnyValueI(reflection::BaseType type, uint8_t* data, int64_t val);
|
|
||||||
void SetAnyValueF(reflection::BaseType type, uint8_t* data, double val);
|
|
||||||
void SetAnyValueS(reflection::BaseType type, uint8_t* data, const char* val);
|
|
||||||
|
|
||||||
// Set any table field as a 64bit int, regardless of type what it is.
|
|
||||||
inline bool SetAnyFieldI(Table* table, const reflection::Field& field,
|
|
||||||
int64_t val) {
|
|
||||||
auto field_ptr = table->GetAddressOf(field.offset());
|
|
||||||
if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field);
|
|
||||||
SetAnyValueI(field.type()->base_type(), field_ptr, val);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set any table field as a double, regardless of what type it is.
|
|
||||||
inline bool SetAnyFieldF(Table* table, const reflection::Field& field,
|
|
||||||
double val) {
|
|
||||||
auto field_ptr = table->GetAddressOf(field.offset());
|
|
||||||
if (!field_ptr) return val == GetFieldDefaultF<double>(field);
|
|
||||||
SetAnyValueF(field.type()->base_type(), field_ptr, val);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set any table field as a string, regardless of what type it is.
|
|
||||||
inline bool SetAnyFieldS(Table* table, const reflection::Field& field,
|
|
||||||
const char* val) {
|
|
||||||
auto field_ptr = table->GetAddressOf(field.offset());
|
|
||||||
if (!field_ptr) return false;
|
|
||||||
SetAnyValueS(field.type()->base_type(), field_ptr, val);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set any struct field as a 64bit int, regardless of type what it is.
|
|
||||||
inline void SetAnyFieldI(Struct* st, const reflection::Field& field,
|
|
||||||
int64_t val) {
|
|
||||||
SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()),
|
|
||||||
val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set any struct field as a double, regardless of type what it is.
|
|
||||||
inline void SetAnyFieldF(Struct* st, const reflection::Field& field,
|
|
||||||
double val) {
|
|
||||||
SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()),
|
|
||||||
val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set any struct field as a string, regardless of type what it is.
|
|
||||||
inline void SetAnyFieldS(Struct* st, const reflection::Field& field,
|
|
||||||
const char* val) {
|
|
||||||
SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()),
|
|
||||||
val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set any vector element as a 64bit int, regardless of type what it is.
|
|
||||||
inline void SetAnyVectorElemI(VectorOfAny* vec, reflection::BaseType elem_type,
|
|
||||||
size_t i, int64_t val) {
|
|
||||||
SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set any vector element as a double, regardless of type what it is.
|
|
||||||
inline void SetAnyVectorElemF(VectorOfAny* vec, reflection::BaseType elem_type,
|
|
||||||
size_t i, double val) {
|
|
||||||
SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set any vector element as a string, regardless of type what it is.
|
|
||||||
inline void SetAnyVectorElemS(VectorOfAny* vec, reflection::BaseType elem_type,
|
|
||||||
size_t i, const char* val) {
|
|
||||||
SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------- RESIZING SETTERS -------------------------
|
|
||||||
|
|
||||||
// "smart" pointer for use with resizing vectors: turns a pointer inside
|
|
||||||
// a vector into a relative offset, such that it is not affected by resizes.
|
|
||||||
template <typename T, typename U>
|
|
||||||
class pointer_inside_vector {
|
|
||||||
public:
|
|
||||||
pointer_inside_vector(T* ptr, std::vector<U>& vec)
|
|
||||||
: offset_(reinterpret_cast<uint8_t*>(ptr) -
|
|
||||||
reinterpret_cast<uint8_t*>(vec.data())),
|
|
||||||
vec_(vec) {}
|
|
||||||
|
|
||||||
T* operator*() const {
|
|
||||||
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(vec_.data()) +
|
|
||||||
offset_);
|
|
||||||
}
|
|
||||||
T* operator->() const { return operator*(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t offset_;
|
|
||||||
std::vector<U>& vec_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper to create the above easily without specifying template args.
|
|
||||||
template <typename T, typename U>
|
|
||||||
pointer_inside_vector<T, U> piv(T* ptr, std::vector<U>& vec) {
|
|
||||||
return pointer_inside_vector<T, U>(ptr, vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const char* UnionTypeFieldSuffix() { return "_type"; }
|
|
||||||
|
|
||||||
// Helper to figure out the actual table type a union refers to.
|
|
||||||
inline const reflection::Object& GetUnionType(
|
|
||||||
const reflection::Schema& schema, const reflection::Object& parent,
|
|
||||||
const reflection::Field& unionfield, const Table& table) {
|
|
||||||
auto enumdef = schema.enums()->Get(unionfield.type()->index());
|
|
||||||
// TODO: this is clumsy and slow, but no other way to find it?
|
|
||||||
auto type_field = parent.fields()->LookupByKey(
|
|
||||||
(unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
|
|
||||||
FLATBUFFERS_ASSERT(type_field);
|
|
||||||
auto union_type = GetFieldI<uint8_t>(table, *type_field);
|
|
||||||
auto enumval = enumdef->values()->LookupByKey(union_type);
|
|
||||||
return *schema.objects()->Get(enumval->union_type()->index());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Changes the contents of a string inside a FlatBuffer. FlatBuffer must
|
|
||||||
// live inside a std::vector so we can resize the buffer if needed.
|
|
||||||
// "str" must live inside "flatbuf" and may be invalidated after this call.
|
|
||||||
// If your FlatBuffer's root table is not the schema's root table, you should
|
|
||||||
// pass in your root_table type as well.
|
|
||||||
void SetString(const reflection::Schema& schema, const std::string& val,
|
|
||||||
const String* str, std::vector<uint8_t>* flatbuf,
|
|
||||||
const reflection::Object* root_table = nullptr);
|
|
||||||
|
|
||||||
// Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must
|
|
||||||
// live inside a std::vector so we can resize the buffer if needed.
|
|
||||||
// "vec" must live inside "flatbuf" and may be invalidated after this call.
|
|
||||||
// If your FlatBuffer's root table is not the schema's root table, you should
|
|
||||||
// pass in your root_table type as well.
|
|
||||||
uint8_t* ResizeAnyVector(const reflection::Schema& schema, uoffset_t newsize,
|
|
||||||
const VectorOfAny* vec, uoffset_t num_elems,
|
|
||||||
uoffset_t elem_size, std::vector<uint8_t>* flatbuf,
|
|
||||||
const reflection::Object* root_table = nullptr);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void ResizeVector(const reflection::Schema& schema, uoffset_t newsize, T val,
|
|
||||||
const Vector<T>* vec, std::vector<uint8_t>* flatbuf,
|
|
||||||
const reflection::Object* root_table = nullptr) {
|
|
||||||
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
|
|
||||||
auto newelems = ResizeAnyVector(
|
|
||||||
schema, newsize, reinterpret_cast<const VectorOfAny*>(vec), vec->size(),
|
|
||||||
static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
|
|
||||||
// Set new elements to "val".
|
|
||||||
for (int i = 0; i < delta_elem; i++) {
|
|
||||||
auto loc = newelems + i * sizeof(T);
|
|
||||||
auto is_scalar = flatbuffers::is_scalar<T>::value;
|
|
||||||
if (is_scalar) {
|
|
||||||
WriteScalar(loc, val);
|
|
||||||
} else { // struct
|
|
||||||
*reinterpret_cast<T*>(loc) = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds any new data (in the form of a new FlatBuffer) to an existing
|
|
||||||
// FlatBuffer. This can be used when any of the above methods are not
|
|
||||||
// sufficient, in particular for adding new tables and new fields.
|
|
||||||
// This is potentially slightly less efficient than a FlatBuffer constructed
|
|
||||||
// in one piece, since the new FlatBuffer doesn't share any vtables with the
|
|
||||||
// existing one.
|
|
||||||
// The return value can now be set using Vector::MutateOffset or SetFieldT
|
|
||||||
// below.
|
|
||||||
const uint8_t* AddFlatBuffer(std::vector<uint8_t>& flatbuf,
|
|
||||||
const uint8_t* newbuf, size_t newlen);
|
|
||||||
|
|
||||||
inline bool SetFieldT(Table* table, const reflection::Field& field,
|
|
||||||
const uint8_t* val) {
|
|
||||||
FLATBUFFERS_ASSERT(sizeof(uoffset_t) ==
|
|
||||||
GetTypeSize(field.type()->base_type()));
|
|
||||||
return table->SetPointer(field.offset(), val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------- COPYING -------------------------
|
|
||||||
|
|
||||||
// Generic copying of tables from a FlatBuffer into a FlatBuffer builder.
|
|
||||||
// Can be used to do any kind of merging/selecting you may want to do out
|
|
||||||
// of existing buffers. Also useful to reconstruct a whole buffer if the
|
|
||||||
// above resizing functionality has introduced garbage in a buffer you want
|
|
||||||
// to remove.
|
|
||||||
// Note: this does not deal with DAGs correctly. If the table passed forms a
|
|
||||||
// DAG, the copy will be a tree instead (with duplicates). Strings can be
|
|
||||||
// shared however, by passing true for use_string_pooling.
|
|
||||||
|
|
||||||
Offset<const Table*> CopyTable(FlatBufferBuilder& fbb,
|
|
||||||
const reflection::Schema& schema,
|
|
||||||
const reflection::Object& objectdef,
|
|
||||||
const Table& table,
|
|
||||||
bool use_string_pooling = false);
|
|
||||||
|
|
||||||
// Verifies the provided flatbuffer using reflection.
|
|
||||||
// root should point to the root type for this flatbuffer.
|
|
||||||
// buf should point to the start of flatbuffer data.
|
|
||||||
// length specifies the size of the flatbuffer data.
|
|
||||||
bool Verify(const reflection::Schema& schema, const reflection::Object& root,
|
|
||||||
const uint8_t* buf, size_t length, uoffset_t max_depth = 64,
|
|
||||||
uoffset_t max_tables = 1000000);
|
|
||||||
|
|
||||||
bool VerifySizePrefixed(const reflection::Schema& schema,
|
|
||||||
const reflection::Object& root, const uint8_t* buf,
|
|
||||||
size_t length, uoffset_t max_depth = 64,
|
|
||||||
uoffset_t max_tables = 1000000);
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_REFLECTION_H_
|
|
||||||
-1541
File diff suppressed because it is too large
Load Diff
@@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_REGISTRY_H_
|
|
||||||
#define FLATBUFFERS_REGISTRY_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/idl.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
|
|
||||||
// Simply pre-populate it with all schema filenames that may be in use, and
|
|
||||||
// This class will look them up using the file_identifier declared in the
|
|
||||||
// schema.
|
|
||||||
class Registry {
|
|
||||||
public:
|
|
||||||
// Call this for all schemas that may be in use. The identifier has
|
|
||||||
// a function in the generated code, e.g. MonsterIdentifier().
|
|
||||||
void Register(const char* file_identifier, const char* schema_path) {
|
|
||||||
Schema schema;
|
|
||||||
schema.path_ = schema_path;
|
|
||||||
schemas_[file_identifier] = schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate text from an arbitrary FlatBuffer by looking up its
|
|
||||||
// file_identifier in the registry.
|
|
||||||
bool FlatBufferToText(const uint8_t* flatbuf, size_t len, std::string* dest) {
|
|
||||||
// Get the identifier out of the buffer.
|
|
||||||
// If the buffer is truncated, exit.
|
|
||||||
if (len < sizeof(uoffset_t) + kFileIdentifierLength) {
|
|
||||||
lasterror_ = "buffer truncated";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::string ident(
|
|
||||||
reinterpret_cast<const char*>(flatbuf) + sizeof(uoffset_t),
|
|
||||||
kFileIdentifierLength);
|
|
||||||
// Load and parse the schema.
|
|
||||||
Parser parser;
|
|
||||||
if (!LoadSchema(ident, &parser)) return false;
|
|
||||||
// Now we're ready to generate text.
|
|
||||||
auto err = GenText(parser, flatbuf, dest);
|
|
||||||
if (err) {
|
|
||||||
lasterror_ =
|
|
||||||
"unable to generate text for FlatBuffer binary: " + std::string(err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a binary buffer to text using one of the schemas in the registry,
|
|
||||||
// use the file_identifier to indicate which.
|
|
||||||
// If DetachedBuffer::data() is null then parsing failed.
|
|
||||||
DetachedBuffer TextToFlatBuffer(const char* text,
|
|
||||||
const char* file_identifier) {
|
|
||||||
// Load and parse the schema.
|
|
||||||
Parser parser;
|
|
||||||
if (!LoadSchema(file_identifier, &parser)) return DetachedBuffer();
|
|
||||||
// Parse the text.
|
|
||||||
if (!parser.Parse(text)) {
|
|
||||||
lasterror_ = parser.error_;
|
|
||||||
return DetachedBuffer();
|
|
||||||
}
|
|
||||||
// We have a valid FlatBuffer. Detach it from the builder and return.
|
|
||||||
return parser.builder_.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify any parsing / output options used by the other functions.
|
|
||||||
void SetOptions(const IDLOptions& opts) { opts_ = opts; }
|
|
||||||
|
|
||||||
// If schemas used contain include statements, call this function for every
|
|
||||||
// directory the parser should search them for.
|
|
||||||
void AddIncludeDirectory(const char* path) { include_paths_.push_back(path); }
|
|
||||||
|
|
||||||
// Returns a human readable error if any of the above functions fail.
|
|
||||||
const std::string& GetLastError() { return lasterror_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool LoadSchema(const std::string& ident, Parser* parser) {
|
|
||||||
// Find the schema, if not, exit.
|
|
||||||
auto it = schemas_.find(ident);
|
|
||||||
if (it == schemas_.end()) {
|
|
||||||
// Don't attach the identifier, since it may not be human readable.
|
|
||||||
lasterror_ = "identifier for this buffer not in the registry";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto& schema = it->second;
|
|
||||||
// Load the schema from disk. If not, exit.
|
|
||||||
std::string schematext;
|
|
||||||
if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
|
|
||||||
lasterror_ = "could not load schema: " + schema.path_;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Parse schema.
|
|
||||||
parser->opts = opts_;
|
|
||||||
if (!parser->Parse(schematext.c_str(), include_paths_.data(),
|
|
||||||
schema.path_.c_str())) {
|
|
||||||
lasterror_ = parser->error_;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Schema {
|
|
||||||
std::string path_;
|
|
||||||
// TODO(wvo) optionally cache schema file or parsed schema here.
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string lasterror_;
|
|
||||||
IDLOptions opts_;
|
|
||||||
std::vector<const char*> include_paths_;
|
|
||||||
std::map<std::string, Schema> schemas_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_REGISTRY_H_
|
|
||||||
@@ -1,516 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_STL_EMULATION_H_
|
|
||||||
#define FLATBUFFERS_STL_EMULATION_H_
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_USE_STD_OPTIONAL
|
|
||||||
// Detect C++17 compatible compiler.
|
|
||||||
// __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
|
|
||||||
#if (defined(__cplusplus) && __cplusplus >= 201703L) \
|
|
||||||
|| (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
|
||||||
#define FLATBUFFERS_USE_STD_OPTIONAL 1
|
|
||||||
#else
|
|
||||||
#define FLATBUFFERS_USE_STD_OPTIONAL 0
|
|
||||||
#endif // (defined(__cplusplus) && __cplusplus >= 201703L) ...
|
|
||||||
#endif // FLATBUFFERS_USE_STD_OPTIONAL
|
|
||||||
|
|
||||||
#if FLATBUFFERS_USE_STD_OPTIONAL
|
|
||||||
#include <optional>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_USE_STD_SPAN
|
|
||||||
// Testing __cpp_lib_span requires including either <version> or <span>,
|
|
||||||
// both of which were added in C++20.
|
|
||||||
// See: https://en.cppreference.com/w/cpp/utility/feature_test
|
|
||||||
#if defined(__cplusplus) && __cplusplus >= 202002L \
|
|
||||||
|| (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
|
||||||
#if __has_include(<span>)
|
|
||||||
#define FLATBUFFERS_USE_STD_SPAN 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif // FLATBUFFERS_USE_STD_SPAN
|
|
||||||
|
|
||||||
#if defined(FLATBUFFERS_USE_STD_SPAN)
|
|
||||||
#include <array>
|
|
||||||
#include <span>
|
|
||||||
#else
|
|
||||||
// Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined.
|
|
||||||
#if !defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
|
||||||
#define FLATBUFFERS_SPAN_MINIMAL
|
|
||||||
#else
|
|
||||||
// Enable implicit construction of a span<T,N> from a std::array<T,N>.
|
|
||||||
#include <array>
|
|
||||||
#endif
|
|
||||||
#endif // defined(FLATBUFFERS_USE_STD_SPAN)
|
|
||||||
|
|
||||||
// This header provides backwards compatibility for older versions of the STL.
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
|
||||||
template <typename T>
|
|
||||||
using numeric_limits = std::numeric_limits<T>;
|
|
||||||
#else
|
|
||||||
template <typename T> class numeric_limits :
|
|
||||||
public std::numeric_limits<T> {};
|
|
||||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
|
||||||
|
|
||||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
|
||||||
template <typename T> using is_scalar = std::is_scalar<T>;
|
|
||||||
template <typename T, typename U> using is_same = std::is_same<T,U>;
|
|
||||||
template <typename T> using is_floating_point = std::is_floating_point<T>;
|
|
||||||
template <typename T> using is_unsigned = std::is_unsigned<T>;
|
|
||||||
template <typename T> using is_enum = std::is_enum<T>;
|
|
||||||
template <typename T> using make_unsigned = std::make_unsigned<T>;
|
|
||||||
template<bool B, class T, class F>
|
|
||||||
using conditional = std::conditional<B, T, F>;
|
|
||||||
template<class T, T v>
|
|
||||||
using integral_constant = std::integral_constant<T, v>;
|
|
||||||
template <bool B>
|
|
||||||
using bool_constant = integral_constant<bool, B>;
|
|
||||||
using true_type = std::true_type;
|
|
||||||
using false_type = std::false_type;
|
|
||||||
#else
|
|
||||||
// MSVC 2010 doesn't support C++11 aliases.
|
|
||||||
template <typename T> struct is_scalar : public std::is_scalar<T> {};
|
|
||||||
template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
|
|
||||||
template <typename T> struct is_floating_point :
|
|
||||||
public std::is_floating_point<T> {};
|
|
||||||
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
|
|
||||||
template <typename T> struct is_enum : public std::is_enum<T> {};
|
|
||||||
template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
|
|
||||||
template<bool B, class T, class F>
|
|
||||||
struct conditional : public std::conditional<B, T, F> {};
|
|
||||||
template<class T, T v>
|
|
||||||
struct integral_constant : public std::integral_constant<T, v> {};
|
|
||||||
template <bool B>
|
|
||||||
struct bool_constant : public integral_constant<bool, B> {};
|
|
||||||
typedef bool_constant<true> true_type;
|
|
||||||
typedef bool_constant<false> false_type;
|
|
||||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
|
||||||
|
|
||||||
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
|
||||||
template <class T> using unique_ptr = std::unique_ptr<T>;
|
|
||||||
#else
|
|
||||||
// MSVC 2010 doesn't support C++11 aliases.
|
|
||||||
// We're manually "aliasing" the class here as we want to bring unique_ptr
|
|
||||||
// into the flatbuffers namespace. We have unique_ptr in the flatbuffers
|
|
||||||
// namespace we have a completely independent implementation (see below)
|
|
||||||
// for C++98 STL implementations.
|
|
||||||
template <class T> class unique_ptr : public std::unique_ptr<T> {
|
|
||||||
public:
|
|
||||||
unique_ptr() {}
|
|
||||||
explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
|
|
||||||
unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
|
|
||||||
unique_ptr(unique_ptr&& u) { *this = std::move(u); }
|
|
||||||
unique_ptr& operator=(std::unique_ptr<T>&& u) {
|
|
||||||
std::unique_ptr<T>::reset(u.release());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
unique_ptr& operator=(unique_ptr&& u) {
|
|
||||||
std::unique_ptr<T>::reset(u.release());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
unique_ptr& operator=(T* p) {
|
|
||||||
return std::unique_ptr<T>::operator=(p);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
|
||||||
|
|
||||||
#if FLATBUFFERS_USE_STD_OPTIONAL
|
|
||||||
template<class T>
|
|
||||||
using Optional = std::optional<T>;
|
|
||||||
using nullopt_t = std::nullopt_t;
|
|
||||||
inline constexpr nullopt_t nullopt = std::nullopt;
|
|
||||||
|
|
||||||
#else
|
|
||||||
// Limited implementation of Optional<T> type for a scalar T.
|
|
||||||
// This implementation limited by trivial types compatible with
|
|
||||||
// std::is_arithmetic<T> or std::is_enum<T> type traits.
|
|
||||||
|
|
||||||
// A tag to indicate an empty flatbuffers::optional<T>.
|
|
||||||
struct nullopt_t {
|
|
||||||
explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(FLATBUFFERS_CONSTEXPR_DEFINED)
|
|
||||||
namespace internal {
|
|
||||||
template <class> struct nullopt_holder {
|
|
||||||
static constexpr nullopt_t instance_ = nullopt_t(0);
|
|
||||||
};
|
|
||||||
template<class Dummy>
|
|
||||||
constexpr nullopt_t nullopt_holder<Dummy>::instance_;
|
|
||||||
}
|
|
||||||
static constexpr const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
|
|
||||||
|
|
||||||
#else
|
|
||||||
namespace internal {
|
|
||||||
template <class> struct nullopt_holder {
|
|
||||||
static const nullopt_t instance_;
|
|
||||||
};
|
|
||||||
template<class Dummy>
|
|
||||||
const nullopt_t nullopt_holder<Dummy>::instance_ = nullopt_t(0);
|
|
||||||
}
|
|
||||||
static const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class Optional FLATBUFFERS_FINAL_CLASS {
|
|
||||||
// Non-scalar 'T' would extremely complicated Optional<T>.
|
|
||||||
// Use is_scalar<T> checking because flatbuffers flatbuffers::is_arithmetic<T>
|
|
||||||
// isn't implemented.
|
|
||||||
static_assert(flatbuffers::is_scalar<T>::value, "unexpected type T");
|
|
||||||
|
|
||||||
public:
|
|
||||||
~Optional() {}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT
|
|
||||||
: value_(), has_value_(false) {}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT
|
|
||||||
: value_(), has_value_(false) {}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT
|
|
||||||
: value_(val), has_value_(true) {}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT
|
|
||||||
: value_(other.value_), has_value_(other.has_value_) {}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT {
|
|
||||||
value_ = other.value_;
|
|
||||||
has_value_ = other.has_value_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT {
|
|
||||||
value_ = T();
|
|
||||||
has_value_ = false;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT {
|
|
||||||
value_ = val;
|
|
||||||
has_value_ = true;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() FLATBUFFERS_NOEXCEPT {
|
|
||||||
*this = nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(Optional &other) FLATBUFFERS_NOEXCEPT {
|
|
||||||
std::swap(value_, other.value_);
|
|
||||||
std::swap(has_value_, other.has_value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT {
|
|
||||||
return has_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT {
|
|
||||||
return has_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT {
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const T& value() const {
|
|
||||||
FLATBUFFERS_ASSERT(has_value());
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
T value_or(T default_value) const FLATBUFFERS_NOEXCEPT {
|
|
||||||
return has_value() ? value_ : default_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T value_;
|
|
||||||
bool has_value_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& opt, nullopt_t) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return !opt;
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional<T>& opt) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return !opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return static_cast<bool>(lhs) && (*lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return static_cast<bool>(rhs) && (lhs == *rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return static_cast<bool>(lhs) != static_cast<bool>(rhs)
|
|
||||||
? false
|
|
||||||
: !static_cast<bool>(lhs) ? true : (*lhs == *rhs);
|
|
||||||
}
|
|
||||||
#endif // FLATBUFFERS_USE_STD_OPTIONAL
|
|
||||||
|
|
||||||
|
|
||||||
// Very limited and naive partial implementation of C++20 std::span<T,Extent>.
|
|
||||||
#if defined(FLATBUFFERS_USE_STD_SPAN)
|
|
||||||
inline constexpr std::size_t dynamic_extent = std::dynamic_extent;
|
|
||||||
template<class T, std::size_t Extent = std::dynamic_extent>
|
|
||||||
using span = std::span<T, Extent>;
|
|
||||||
|
|
||||||
#else // !defined(FLATBUFFERS_USE_STD_SPAN)
|
|
||||||
FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1);
|
|
||||||
|
|
||||||
// Exclude this code if MSVC2010 or non-STL Android is active.
|
|
||||||
// The non-STL Android doesn't have `std::is_convertible` required for SFINAE.
|
|
||||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL)
|
|
||||||
namespace internal {
|
|
||||||
// This is SFINAE helper class for checking of a common condition:
|
|
||||||
// > This overload only participates in overload resolution
|
|
||||||
// > Check whether a pointer to an array of From can be converted
|
|
||||||
// > to a pointer to an array of To.
|
|
||||||
// This helper is used for checking of 'From -> const From'.
|
|
||||||
template<class To, std::size_t Extent, class From, std::size_t N>
|
|
||||||
struct is_span_convertible {
|
|
||||||
using type =
|
|
||||||
typename std::conditional<std::is_convertible<From (*)[], To (*)[]>::value
|
|
||||||
&& (Extent == dynamic_extent || N == Extent),
|
|
||||||
int, void>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct SpanIterator {
|
|
||||||
// TODO: upgrade to std::random_access_iterator_tag.
|
|
||||||
using iterator_category = std::forward_iterator_tag;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using value_type = typename std::remove_cv<T>::type;
|
|
||||||
using reference = T&;
|
|
||||||
using pointer = T*;
|
|
||||||
|
|
||||||
// Convince MSVC compiler that this iterator is trusted (it is verified).
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
using _Unchecked_type = pointer;
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
SpanIterator(pointer ptr) : ptr_(ptr) {}
|
|
||||||
reference operator*() const { return *ptr_; }
|
|
||||||
pointer operator->() { return ptr_; }
|
|
||||||
SpanIterator& operator++() { ptr_++; return *this; }
|
|
||||||
SpanIterator operator++(int) { auto tmp = *this; ++(*this); return tmp; }
|
|
||||||
|
|
||||||
friend bool operator== (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ == rhs.ptr_; }
|
|
||||||
friend bool operator!= (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ != rhs.ptr_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
pointer ptr_;
|
|
||||||
};
|
|
||||||
} // namespace internal
|
|
||||||
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
|
|
||||||
|
|
||||||
// T - element type; must be a complete type that is not an abstract
|
|
||||||
// class type.
|
|
||||||
// Extent - the number of elements in the sequence, or dynamic.
|
|
||||||
template<class T, std::size_t Extent = dynamic_extent>
|
|
||||||
class span FLATBUFFERS_FINAL_CLASS {
|
|
||||||
public:
|
|
||||||
typedef T element_type;
|
|
||||||
typedef T& reference;
|
|
||||||
typedef const T& const_reference;
|
|
||||||
typedef T* pointer;
|
|
||||||
typedef const T* const_pointer;
|
|
||||||
typedef std::size_t size_type;
|
|
||||||
|
|
||||||
static FLATBUFFERS_CONSTEXPR size_type extent = Extent;
|
|
||||||
|
|
||||||
// Returns the number of elements in the span.
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT {
|
|
||||||
return count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the size of the sequence in bytes.
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
size_type size_bytes() const FLATBUFFERS_NOEXCEPT {
|
|
||||||
return size() * sizeof(element_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if the span is empty.
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT {
|
|
||||||
return size() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a pointer to the beginning of the sequence.
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT {
|
|
||||||
return data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL)
|
|
||||||
using Iterator = internal::SpanIterator<T>;
|
|
||||||
|
|
||||||
Iterator begin() const { return Iterator(data()); }
|
|
||||||
Iterator end() const { return Iterator(data() + size()); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Returns a reference to the idx-th element of the sequence.
|
|
||||||
// The behavior is undefined if the idx is greater than or equal to size().
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const {
|
|
||||||
return data()[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT
|
|
||||||
: data_(other.data_), count_(other.count_) {}
|
|
||||||
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other)
|
|
||||||
FLATBUFFERS_NOEXCEPT {
|
|
||||||
data_ = other.data_;
|
|
||||||
count_ = other.count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limited implementation of
|
|
||||||
// `template <class It> constexpr std::span(It first, size_type count);`.
|
|
||||||
//
|
|
||||||
// Constructs a span that is a view over the range [first, first + count);
|
|
||||||
// the resulting span has: data() == first and size() == count.
|
|
||||||
// The behavior is undefined if [first, first + count) is not a valid range,
|
|
||||||
// or if (extent != flatbuffers::dynamic_extent && count != extent).
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT
|
|
||||||
: data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)),
|
|
||||||
count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) {
|
|
||||||
// Make span empty if the count argument is incompatible with span<T,N>.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11
|
|
||||||
// compliant, it doesn't support default template arguments for functions.
|
|
||||||
#if defined(FLATBUFFERS_SPAN_MINIMAL)
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
|
|
||||||
count_(0) {
|
|
||||||
static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
// Constructs an empty span whose data() == nullptr and size() == 0.
|
|
||||||
// This overload only participates in overload resolution if
|
|
||||||
// extent == 0 || extent == flatbuffers::dynamic_extent.
|
|
||||||
// A dummy template argument N is need dependency for SFINAE.
|
|
||||||
template<std::size_t N = 0,
|
|
||||||
typename internal::is_span_convertible<element_type, Extent, element_type, (N - N)>::type = 0>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
|
|
||||||
count_(0) {
|
|
||||||
static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructs a span that is a view over the array arr; the resulting span
|
|
||||||
// has size() == N and data() == std::data(arr). These overloads only
|
|
||||||
// participate in overload resolution if
|
|
||||||
// extent == std::dynamic_extent || N == extent is true and
|
|
||||||
// std::remove_pointer_t<decltype(std::data(arr))>(*)[]
|
|
||||||
// is convertible to element_type (*)[].
|
|
||||||
template<std::size_t N,
|
|
||||||
typename internal::is_span_convertible<element_type, Extent, element_type, N>::type = 0>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT
|
|
||||||
: data_(arr), count_(N) {}
|
|
||||||
|
|
||||||
template<class U, std::size_t N,
|
|
||||||
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
|
|
||||||
: data_(arr.data()), count_(N) {}
|
|
||||||
|
|
||||||
//template<class U, std::size_t N,
|
|
||||||
// int = 0>
|
|
||||||
//FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
|
|
||||||
// : data_(arr.data()), count_(N) {}
|
|
||||||
|
|
||||||
template<class U, std::size_t N,
|
|
||||||
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
|
|
||||||
: data_(arr.data()), count_(N) {}
|
|
||||||
|
|
||||||
// Converting constructor from another span s;
|
|
||||||
// the resulting span has size() == s.size() and data() == s.data().
|
|
||||||
// This overload only participates in overload resolution
|
|
||||||
// if extent == std::dynamic_extent || N == extent is true and U (*)[]
|
|
||||||
// is convertible to element_type (*)[].
|
|
||||||
template<class U, std::size_t N,
|
|
||||||
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT
|
|
||||||
: span(s.data(), s.size()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
|
|
||||||
|
|
||||||
private:
|
|
||||||
// This is a naive implementation with 'count_' member even if (Extent != dynamic_extent).
|
|
||||||
pointer const data_;
|
|
||||||
size_type count_;
|
|
||||||
};
|
|
||||||
#endif // defined(FLATBUFFERS_USE_STD_SPAN)
|
|
||||||
|
|
||||||
#if !defined(FLATBUFFERS_SPAN_MINIMAL)
|
|
||||||
template<class ElementType, std::size_t Extent>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
flatbuffers::span<ElementType, Extent> make_span(ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return span<ElementType, Extent>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ElementType, std::size_t Extent>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
flatbuffers::span<const ElementType, Extent> make_span(const ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return span<const ElementType, Extent>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ElementType, std::size_t Extent>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
flatbuffers::span<ElementType, Extent> make_span(std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return span<ElementType, Extent>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ElementType, std::size_t Extent>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
flatbuffers::span<const ElementType, Extent> make_span(const std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return span<const ElementType, Extent>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ElementType, std::size_t Extent>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
flatbuffers::span<ElementType, dynamic_extent> make_span(ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return span<ElementType, dynamic_extent>(first, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ElementType, std::size_t Extent>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11
|
|
||||||
flatbuffers::span<const ElementType, dynamic_extent> make_span(const ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return span<const ElementType, dynamic_extent>(first, count);
|
|
||||||
}
|
|
||||||
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_STL_EMULATION_H_
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_STRING_H_
|
|
||||||
#define FLATBUFFERS_STRING_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/vector.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
struct String : public Vector<char> {
|
|
||||||
const char* c_str() const { return reinterpret_cast<const char*>(Data()); }
|
|
||||||
std::string str() const { return std::string(c_str(), size()); }
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#ifdef FLATBUFFERS_HAS_STRING_VIEW
|
|
||||||
flatbuffers::string_view string_view() const {
|
|
||||||
return flatbuffers::string_view(c_str(), size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* implicit */
|
|
||||||
operator flatbuffers::string_view() const {
|
|
||||||
return flatbuffers::string_view(c_str(), size());
|
|
||||||
}
|
|
||||||
#endif // FLATBUFFERS_HAS_STRING_VIEW
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
bool operator<(const String& o) const {
|
|
||||||
return StringLessThan(this->data(), this->size(), o.data(), o.size());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Convenience function to get std::string from a String returning an empty
|
|
||||||
// string on null pointer.
|
|
||||||
static inline std::string GetString(const String* str) {
|
|
||||||
return str ? str->str() : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convenience function to get char* from a String returning an empty string on
|
|
||||||
// null pointer.
|
|
||||||
static inline const char* GetCstring(const String* str) {
|
|
||||||
return str ? str->c_str() : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef FLATBUFFERS_HAS_STRING_VIEW
|
|
||||||
// Convenience function to get string_view from a String returning an empty
|
|
||||||
// string_view on null pointer.
|
|
||||||
static inline flatbuffers::string_view GetStringView(const String* str) {
|
|
||||||
return str ? str->string_view() : flatbuffers::string_view();
|
|
||||||
}
|
|
||||||
#endif // FLATBUFFERS_HAS_STRING_VIEW
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_STRING_H_
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_STRUCT_H_
|
|
||||||
#define FLATBUFFERS_STRUCT_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// "structs" are flat structures that do not have an offset table, thus
|
|
||||||
// always have all members present and do not support forwards/backwards
|
|
||||||
// compatible extensions.
|
|
||||||
|
|
||||||
class Struct FLATBUFFERS_FINAL_CLASS {
|
|
||||||
public:
|
|
||||||
template <typename T>
|
|
||||||
T GetField(uoffset_t o) const {
|
|
||||||
return ReadScalar<T>(&data_[o]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T GetStruct(uoffset_t o) const {
|
|
||||||
return reinterpret_cast<T>(&data_[o]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t* GetAddressOf(uoffset_t o) const { return &data_[o]; }
|
|
||||||
uint8_t* GetAddressOf(uoffset_t o) { return &data_[o]; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// private constructor & copy constructor: you obtain instances of this
|
|
||||||
// class by pointing to existing data only
|
|
||||||
Struct();
|
|
||||||
Struct(const Struct&);
|
|
||||||
Struct& operator=(const Struct&);
|
|
||||||
|
|
||||||
uint8_t data_[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_STRUCT_H_
|
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_TABLE_H_
|
|
||||||
#define FLATBUFFERS_TABLE_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/vector.h"
|
|
||||||
#include "flatbuffers/verifier.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// "tables" use an offset table (possibly shared) that allows fields to be
|
|
||||||
// omitted and added at will, but uses an extra indirection to read.
|
|
||||||
class Table {
|
|
||||||
public:
|
|
||||||
const uint8_t* GetVTable() const {
|
|
||||||
return data_ - ReadScalar<soffset_t>(data_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This gets the field offset for any of the functions below it, or 0
|
|
||||||
// if the field was not present.
|
|
||||||
voffset_t GetOptionalFieldOffset(voffset_t field) const {
|
|
||||||
// The vtable offset is always at the start.
|
|
||||||
auto vtable = GetVTable();
|
|
||||||
// The first element is the size of the vtable (fields + type id + itself).
|
|
||||||
auto vtsize = ReadScalar<voffset_t>(vtable);
|
|
||||||
// If the field we're accessing is outside the vtable, we're reading older
|
|
||||||
// data, so it's the same as if the offset was 0 (not present).
|
|
||||||
return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T GetField(voffset_t field, T defaultval) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P, typename OffsetSize = uoffset_t>
|
|
||||||
P GetPointer(voffset_t field) {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
auto p = data_ + field_offset;
|
|
||||||
return field_offset ? reinterpret_cast<P>(p + ReadScalar<OffsetSize>(p))
|
|
||||||
: nullptr;
|
|
||||||
}
|
|
||||||
template <typename P, typename OffsetSize = uoffset_t>
|
|
||||||
P GetPointer(voffset_t field) const {
|
|
||||||
return const_cast<Table*>(this)->GetPointer<P, OffsetSize>(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P>
|
|
||||||
P GetPointer64(voffset_t field) {
|
|
||||||
return GetPointer<P, uoffset64_t>(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P>
|
|
||||||
P GetPointer64(voffset_t field) const {
|
|
||||||
return GetPointer<P, uoffset64_t>(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P, typename SizeT = uoffset_t,
|
|
||||||
typename OffsetSize = uoffset_t>
|
|
||||||
const Vector<P, SizeT>* GetVectorPointerOrEmpty(voffset_t field) const {
|
|
||||||
auto* ptr = GetPointer<const Vector<P, SizeT>*, OffsetSize>(field);
|
|
||||||
return ptr ? ptr : EmptyVector<P, SizeT>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P, typename SizeT = uoffset_t>
|
|
||||||
const Vector<P, SizeT>* GetVectorPointer64OrEmpty(voffset_t field) const {
|
|
||||||
return GetVectorPointerOrEmpty<P, SizeT, uoffset64_t>(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P, typename SizeT = uoffset_t,
|
|
||||||
typename OffsetSize = uoffset_t>
|
|
||||||
Vector<P, SizeT>* GetMutableVectorPointerOrEmpty(voffset_t field) {
|
|
||||||
auto* ptr = GetPointer<Vector<P, SizeT>*, OffsetSize>(field);
|
|
||||||
// This is a const_cast, but safe, since all mutable operations on an
|
|
||||||
// empty vector are NOPs.
|
|
||||||
return ptr ? ptr : const_cast<Vector<P, SizeT>*>(EmptyVector<P, SizeT>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P, typename SizeT = uoffset_t>
|
|
||||||
Vector<P, SizeT>* GetMutableVectorPointer64OrEmpty(voffset_t field) {
|
|
||||||
return GetMutableVectorPointerOrEmpty<P, SizeT, uoffset64_t>(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P>
|
|
||||||
P GetStruct(voffset_t field) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
auto p = const_cast<uint8_t*>(data_ + field_offset);
|
|
||||||
return field_offset ? reinterpret_cast<P>(p) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Raw, typename Face>
|
|
||||||
flatbuffers::Optional<Face> GetOptional(voffset_t field) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
auto p = data_ + field_offset;
|
|
||||||
return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p)))
|
|
||||||
: Optional<Face>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool SetField(voffset_t field, T val, T def) {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
if (!field_offset) return IsTheSameAs(val, def);
|
|
||||||
WriteScalar(data_ + field_offset, val);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
bool SetField(voffset_t field, T val) {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
if (!field_offset) return false;
|
|
||||||
WriteScalar(data_ + field_offset, val);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetPointer(voffset_t field, const uint8_t* val) {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
if (!field_offset) return false;
|
|
||||||
WriteScalar(data_ + field_offset,
|
|
||||||
static_cast<uoffset_t>(val - (data_ + field_offset)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* GetAddressOf(voffset_t field) {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
return field_offset ? data_ + field_offset : nullptr;
|
|
||||||
}
|
|
||||||
const uint8_t* GetAddressOf(voffset_t field) const {
|
|
||||||
return const_cast<Table*>(this)->GetAddressOf(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckField(voffset_t field) const {
|
|
||||||
return GetOptionalFieldOffset(field) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the vtable of this table.
|
|
||||||
// Call this once per table, followed by VerifyField once per field.
|
|
||||||
template <bool B>
|
|
||||||
bool VerifyTableStart(VerifierTemplate<B>& verifier) const {
|
|
||||||
return verifier.VerifyTableStart(data_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify a particular field.
|
|
||||||
template <typename T, bool B>
|
|
||||||
bool VerifyField(const VerifierTemplate<B>& verifier, voffset_t field,
|
|
||||||
size_t align) const {
|
|
||||||
// Calling GetOptionalFieldOffset should be safe now thanks to
|
|
||||||
// VerifyTable().
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
// Check the actual field.
|
|
||||||
return !field_offset ||
|
|
||||||
verifier.template VerifyField<T>(data_, field_offset, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyField for required fields.
|
|
||||||
template <typename T, bool B>
|
|
||||||
bool VerifyFieldRequired(const VerifierTemplate<B>& verifier, voffset_t field,
|
|
||||||
size_t align) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
return verifier.Check(field_offset != 0) &&
|
|
||||||
verifier.template VerifyField<T>(data_, field_offset, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Versions for offsets.
|
|
||||||
template <typename OffsetT = uoffset_t, bool B = false>
|
|
||||||
bool VerifyOffset(const VerifierTemplate<B>& verifier,
|
|
||||||
voffset_t field) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
return !field_offset ||
|
|
||||||
verifier.template VerifyOffset<OffsetT>(data_, field_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OffsetT = uoffset_t, bool B = false>
|
|
||||||
bool VerifyOffsetRequired(const VerifierTemplate<B>& verifier,
|
|
||||||
voffset_t field) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
return verifier.Check(field_offset != 0) &&
|
|
||||||
verifier.template VerifyOffset<OffsetT>(data_, field_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool B>
|
|
||||||
bool VerifyOffset64(const VerifierTemplate<B>& verifier,
|
|
||||||
voffset_t field) const {
|
|
||||||
return VerifyOffset<uoffset64_t>(verifier, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool B>
|
|
||||||
bool VerifyOffset64Required(const VerifierTemplate<B>& verifier,
|
|
||||||
voffset_t field) const {
|
|
||||||
return VerifyOffsetRequired<uoffset64_t>(verifier, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify a string that may have a default value.
|
|
||||||
template <typename OffsetT = uoffset_t>
|
|
||||||
bool VerifyStringWithDefault(const Verifier& verifier,
|
|
||||||
voffset_t field) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
return field_offset == 0 ||
|
|
||||||
verifier.VerifyString(GetPointer<const String*, OffsetT>(field));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify a vector that has a default empty value.
|
|
||||||
template <typename P, typename SizeT = uoffset_t,
|
|
||||||
typename OffsetSize = uoffset_t>
|
|
||||||
bool VerifyVectorWithDefault(const Verifier& verifier,
|
|
||||||
voffset_t field) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
return field_offset == 0 ||
|
|
||||||
verifier.VerifyVector(
|
|
||||||
GetPointer<const Vector<P, SizeT>*, OffsetSize>(field));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P, typename SizeT = uoffset_t>
|
|
||||||
bool VerifyVector64WithDefault(const Verifier& verifier,
|
|
||||||
voffset_t field) const {
|
|
||||||
return VerifyVectorWithDefault<P, SizeT, uoffset64_t>(verifier, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
template <typename T, typename SizeT = uoffset_t>
|
|
||||||
static const Vector<T, SizeT>* EmptyVector() {
|
|
||||||
static const SizeT empty_vector_length = 0;
|
|
||||||
return reinterpret_cast<const Vector<T, SizeT>*>(&empty_vector_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// private constructor & copy constructor: you obtain instances of this
|
|
||||||
// class by pointing to existing data only
|
|
||||||
Table();
|
|
||||||
Table(const Table& other);
|
|
||||||
Table& operator=(const Table&);
|
|
||||||
|
|
||||||
uint8_t data_[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
// This specialization allows avoiding warnings like:
|
|
||||||
// MSVC C4800: type: forcing value to bool 'true' or 'false'.
|
|
||||||
template <>
|
|
||||||
inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
|
|
||||||
voffset_t field) const {
|
|
||||||
auto field_offset = GetOptionalFieldOffset(field);
|
|
||||||
auto p = data_ + field_offset;
|
|
||||||
return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0)
|
|
||||||
: Optional<bool>();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_TABLE_H_
|
|
||||||
@@ -1,781 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_UTIL_H_
|
|
||||||
#define FLATBUFFERS_UTIL_H_
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/stl_emulation.h"
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
|
||||||
#include <iomanip>
|
|
||||||
#include <sstream>
|
|
||||||
#else // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
#include <float.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <limits>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// @locale-independent functions for ASCII characters set.
|
|
||||||
|
|
||||||
// Fast checking that character lies in closed range: [a <= x <= b]
|
|
||||||
// using one compare (conditional branch) operator.
|
|
||||||
inline bool check_ascii_range(char x, char a, char b) {
|
|
||||||
FLATBUFFERS_ASSERT(a <= b);
|
|
||||||
// (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`.
|
|
||||||
// The x, a, b will be promoted to int and subtracted without overflow.
|
|
||||||
return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Case-insensitive isalpha
|
|
||||||
inline bool is_alpha(char c) {
|
|
||||||
// ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
|
|
||||||
return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for uppercase alpha
|
|
||||||
inline bool is_alpha_upper(char c) { return check_ascii_range(c, 'A', 'Z'); }
|
|
||||||
|
|
||||||
// Check (case-insensitive) that `c` is equal to alpha.
|
|
||||||
inline bool is_alpha_char(char c, char alpha) {
|
|
||||||
FLATBUFFERS_ASSERT(is_alpha(alpha));
|
|
||||||
// ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
|
|
||||||
return ((c & 0xDF) == (alpha & 0xDF));
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://en.cppreference.com/w/cpp/string/byte/isxdigit
|
|
||||||
// isdigit and isxdigit are the only standard narrow character classification
|
|
||||||
// functions that are not affected by the currently installed C locale. although
|
|
||||||
// some implementations (e.g. Microsoft in 1252 codepage) may classify
|
|
||||||
// additional single-byte characters as digits.
|
|
||||||
inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); }
|
|
||||||
|
|
||||||
inline bool is_xdigit(char c) {
|
|
||||||
// Replace by look-up table.
|
|
||||||
return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Case-insensitive isalnum
|
|
||||||
inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); }
|
|
||||||
|
|
||||||
inline char CharToUpper(char c) {
|
|
||||||
return static_cast<char>(::toupper(static_cast<unsigned char>(c)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char CharToLower(char c) {
|
|
||||||
return static_cast<char>(::tolower(static_cast<unsigned char>(c)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// @end-locale-independent functions for ASCII character set
|
|
||||||
|
|
||||||
#ifdef FLATBUFFERS_PREFER_PRINTF
|
|
||||||
template <typename T>
|
|
||||||
size_t IntToDigitCount(T t) {
|
|
||||||
size_t digit_count = 0;
|
|
||||||
// Count the sign for negative numbers
|
|
||||||
if (t < 0) digit_count++;
|
|
||||||
// Count a single 0 left of the dot for fractional numbers
|
|
||||||
if (-1 < t && t < 1) digit_count++;
|
|
||||||
// Count digits until fractional part
|
|
||||||
T eps = std::numeric_limits<T>::epsilon();
|
|
||||||
while (t <= (-1 + eps) || (1 - eps) <= t) {
|
|
||||||
t /= 10;
|
|
||||||
digit_count++;
|
|
||||||
}
|
|
||||||
return digit_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
size_t NumToStringWidth(T t, int precision = 0) {
|
|
||||||
size_t string_width = IntToDigitCount(t);
|
|
||||||
// Count the dot for floating point numbers
|
|
||||||
if (precision) string_width += (precision + 1);
|
|
||||||
return string_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::string NumToStringImplWrapper(T t, const char* fmt, int precision = 0) {
|
|
||||||
size_t string_width = NumToStringWidth(t, precision);
|
|
||||||
std::string s(string_width, 0x00);
|
|
||||||
// Allow snprintf to use std::string trailing null to detect buffer overflow
|
|
||||||
snprintf(const_cast<char*>(s.data()), (s.size() + 1), fmt, string_width, t);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
|
|
||||||
// Convert an integer or floating point value to a string.
|
|
||||||
// In contrast to std::stringstream, "char" values are
|
|
||||||
// converted to a string of digits, and we don't use scientific notation.
|
|
||||||
template <typename T>
|
|
||||||
std::string NumToString(T t) {
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << t;
|
|
||||||
return ss.str();
|
|
||||||
#else // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
auto v = static_cast<long long>(t);
|
|
||||||
return NumToStringImplWrapper(v, "%.*lld");
|
|
||||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
// Avoid char types used as character data.
|
|
||||||
template <>
|
|
||||||
inline std::string NumToString<signed char>(signed char t) {
|
|
||||||
return NumToString(static_cast<int>(t));
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
inline std::string NumToString<unsigned char>(unsigned char t) {
|
|
||||||
return NumToString(static_cast<int>(t));
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
inline std::string NumToString<char>(char t) {
|
|
||||||
return NumToString(static_cast<int>(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special versions for floats/doubles.
|
|
||||||
template <typename T>
|
|
||||||
std::string FloatToString(T t, int precision) {
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
|
||||||
// to_string() prints different numbers of digits for floats depending on
|
|
||||||
// platform and isn't available on Android, so we use stringstream
|
|
||||||
std::stringstream ss;
|
|
||||||
// Use std::fixed to suppress scientific notation.
|
|
||||||
ss << std::fixed;
|
|
||||||
// Default precision is 6, we want that to be higher for doubles.
|
|
||||||
ss << std::setprecision(precision);
|
|
||||||
ss << t;
|
|
||||||
auto s = ss.str();
|
|
||||||
#else // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
auto v = static_cast<double>(t);
|
|
||||||
auto s = NumToStringImplWrapper(v, "%0.*f", precision);
|
|
||||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
// clang-format on
|
|
||||||
// Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
|
|
||||||
auto p = s.find_last_not_of('0');
|
|
||||||
if (p != std::string::npos) {
|
|
||||||
// Strip trailing zeroes. If it is a whole number, keep one zero.
|
|
||||||
s.resize(p + (s[p] == '.' ? 2 : 1));
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline std::string NumToString<double>(double t) {
|
|
||||||
return FloatToString(t, 12);
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
inline std::string NumToString<float>(float t) {
|
|
||||||
return FloatToString(t, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert an integer value to a hexadecimal string.
|
|
||||||
// The returned string length is always xdigits long, prefixed by 0 digits.
|
|
||||||
// For example, IntToStringHex(0x23, 8) returns the string "00000023".
|
|
||||||
inline std::string IntToStringHex(int i, int xdigits) {
|
|
||||||
FLATBUFFERS_ASSERT(i >= 0);
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
|
|
||||||
<< i;
|
|
||||||
return ss.str();
|
|
||||||
#else // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
return NumToStringImplWrapper(i, "%.*X", xdigits);
|
|
||||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}.
|
|
||||||
#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
|
|
||||||
class ClassicLocale {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
typedef _locale_t locale_type;
|
|
||||||
#else
|
|
||||||
typedef locale_t locale_type; // POSIX.1-2008 locale_t type
|
|
||||||
#endif
|
|
||||||
ClassicLocale();
|
|
||||||
~ClassicLocale();
|
|
||||||
locale_type locale_;
|
|
||||||
static ClassicLocale instance_;
|
|
||||||
public:
|
|
||||||
static locale_type Get() { return instance_.locale_; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get())
|
|
||||||
#define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get())
|
|
||||||
#define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get())
|
|
||||||
#define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get())
|
|
||||||
#else
|
|
||||||
#define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get())
|
|
||||||
#define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get())
|
|
||||||
#define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get())
|
|
||||||
#define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get())
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define __strtod_impl(s, pe) strtod(s, pe)
|
|
||||||
#define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe))
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b)
|
|
||||||
#define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b)
|
|
||||||
#else
|
|
||||||
#define __strtoull_impl(s, pe, b) strtoull(s, pe, b)
|
|
||||||
#define __strtoll_impl(s, pe, b) strtoll(s, pe, b)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline void strtoval_impl(int64_t *val, const char *str, char **endptr,
|
|
||||||
int base) {
|
|
||||||
*val = __strtoll_impl(str, endptr, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void strtoval_impl(uint64_t *val, const char *str, char **endptr,
|
|
||||||
int base) {
|
|
||||||
*val = __strtoull_impl(str, endptr, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void strtoval_impl(double *val, const char *str, char **endptr) {
|
|
||||||
*val = __strtod_impl(str, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
|
|
||||||
FLATBUFFERS_SUPPRESS_UBSAN("float-cast-overflow")
|
|
||||||
inline void strtoval_impl(float *val, const char *str, char **endptr) {
|
|
||||||
*val = __strtof_impl(str, endptr);
|
|
||||||
}
|
|
||||||
#undef __strtoull_impl
|
|
||||||
#undef __strtoll_impl
|
|
||||||
#undef __strtod_impl
|
|
||||||
#undef __strtof_impl
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
// Adaptor for strtoull()/strtoll().
|
|
||||||
// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9),
|
|
||||||
// while strtoll with base=0 interprets first leading zero as octal prefix.
|
|
||||||
// In future, it is possible to add prefixed 0b0101.
|
|
||||||
// 1) Checks errno code for overflow condition (out of range).
|
|
||||||
// 2) If base <= 0, function try to detect base of number by prefix.
|
|
||||||
//
|
|
||||||
// Return value (like strtoull and strtoll, but reject partial result):
|
|
||||||
// - If successful, an integer value corresponding to the str is returned.
|
|
||||||
// - If full string conversion can't be performed, 0 is returned.
|
|
||||||
// - If the converted value falls out of range of corresponding return type, a
|
|
||||||
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
|
|
||||||
template <typename T>
|
|
||||||
inline bool StringToIntegerImpl(T* val, const char* const str,
|
|
||||||
const int base = 0,
|
|
||||||
const bool check_errno = true) {
|
|
||||||
// T is int64_t or uint64_T
|
|
||||||
FLATBUFFERS_ASSERT(str);
|
|
||||||
if (base <= 0) {
|
|
||||||
auto s = str;
|
|
||||||
while (*s && !is_digit(*s)) s++;
|
|
||||||
if (s[0] == '0' && is_alpha_char(s[1], 'X'))
|
|
||||||
return StringToIntegerImpl(val, str, 16, check_errno);
|
|
||||||
// if a prefix not match, try base=10
|
|
||||||
return StringToIntegerImpl(val, str, 10, check_errno);
|
|
||||||
} else {
|
|
||||||
if (check_errno) errno = 0; // clear thread-local errno
|
|
||||||
auto endptr = str;
|
|
||||||
strtoval_impl(val, str, const_cast<char**>(&endptr), base);
|
|
||||||
if ((*endptr != '\0') || (endptr == str)) {
|
|
||||||
*val = 0; // erase partial result
|
|
||||||
return false; // invalid string
|
|
||||||
}
|
|
||||||
// errno is out-of-range, return MAX/MIN
|
|
||||||
if (check_errno && errno) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool StringToFloatImpl(T* val, const char* const str) {
|
|
||||||
// Type T must be either float or double.
|
|
||||||
FLATBUFFERS_ASSERT(str && val);
|
|
||||||
auto end = str;
|
|
||||||
strtoval_impl(val, str, const_cast<char**>(&end));
|
|
||||||
auto done = (end != str) && (*end == '\0');
|
|
||||||
if (!done) *val = 0; // erase partial result
|
|
||||||
if (done && std::isnan(*val)) {
|
|
||||||
*val = std::numeric_limits<T>::quiet_NaN();
|
|
||||||
}
|
|
||||||
return done;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a string to an instance of T.
|
|
||||||
// Return value (matched with StringToInteger64Impl and strtod):
|
|
||||||
// - If successful, a numeric value corresponding to the str is returned.
|
|
||||||
// - If full string conversion can't be performed, 0 is returned.
|
|
||||||
// - If the converted value falls out of range of corresponding return type, a
|
|
||||||
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
|
|
||||||
template <typename T>
|
|
||||||
inline bool StringToNumber(const char* s, T* val) {
|
|
||||||
// Assert on `unsigned long` and `signed long` on LP64.
|
|
||||||
// If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
|
|
||||||
static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
|
|
||||||
FLATBUFFERS_ASSERT(s && val);
|
|
||||||
int64_t i64;
|
|
||||||
// The errno check isn't needed, will return MAX/MIN on overflow.
|
|
||||||
if (StringToIntegerImpl(&i64, s, 0, false)) {
|
|
||||||
const int64_t max = (flatbuffers::numeric_limits<T>::max)();
|
|
||||||
const int64_t min = flatbuffers::numeric_limits<T>::lowest();
|
|
||||||
if (i64 > max) {
|
|
||||||
*val = static_cast<T>(max);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (i64 < min) {
|
|
||||||
// For unsigned types return max to distinguish from
|
|
||||||
// "no conversion can be performed" when 0 is returned.
|
|
||||||
*val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*val = static_cast<T>(i64);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*val = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool StringToNumber<int64_t>(const char* str, int64_t* val) {
|
|
||||||
return StringToIntegerImpl(val, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool StringToNumber<uint64_t>(const char* str, uint64_t* val) {
|
|
||||||
if (!StringToIntegerImpl(val, str)) return false;
|
|
||||||
// The strtoull accepts negative numbers:
|
|
||||||
// If the minus sign was part of the input sequence, the numeric value
|
|
||||||
// calculated from the sequence of digits is negated as if by unary minus
|
|
||||||
// in the result type, which applies unsigned integer wraparound rules.
|
|
||||||
// Fix this behaviour (except -0).
|
|
||||||
if (*val) {
|
|
||||||
auto s = str;
|
|
||||||
while (*s && !is_digit(*s)) s++;
|
|
||||||
s = (s > str) ? (s - 1) : s; // step back to one symbol
|
|
||||||
if (*s == '-') {
|
|
||||||
// For unsigned types return the max to distinguish from
|
|
||||||
// "no conversion can be performed".
|
|
||||||
*val = (flatbuffers::numeric_limits<uint64_t>::max)();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool StringToNumber(const char* s, float* val) {
|
|
||||||
return StringToFloatImpl(val, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool StringToNumber(const char* s, double* val) {
|
|
||||||
return StringToFloatImpl(val, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t StringToInt(const char* s, int base = 10) {
|
|
||||||
int64_t val;
|
|
||||||
return StringToIntegerImpl(&val, s, base) ? val : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t StringToUInt(const char* s, int base = 10) {
|
|
||||||
uint64_t val;
|
|
||||||
return StringToIntegerImpl(&val, s, base) ? val : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool StringIsFlatbufferNan(const std::string& s) {
|
|
||||||
return s == "nan" || s == "+nan" || s == "-nan";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool StringIsFlatbufferPositiveInfinity(const std::string& s) {
|
|
||||||
return s == "inf" || s == "+inf" || s == "infinity" || s == "+infinity";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool StringIsFlatbufferNegativeInfinity(const std::string& s) {
|
|
||||||
return s == "-inf" || s == "-infinity";
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef bool (*LoadFileFunction)(const char* filename, bool binary,
|
|
||||||
std::string* dest);
|
|
||||||
typedef bool (*FileExistsFunction)(const char* filename);
|
|
||||||
|
|
||||||
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
|
|
||||||
|
|
||||||
FileExistsFunction SetFileExistsFunction(
|
|
||||||
FileExistsFunction file_exists_function);
|
|
||||||
|
|
||||||
// Check if file "name" exists.
|
|
||||||
bool FileExists(const char* name);
|
|
||||||
|
|
||||||
// Check if "name" exists and it is also a directory.
|
|
||||||
bool DirExists(const char* name);
|
|
||||||
|
|
||||||
// Load file "name" into "buf" returning true if successful
|
|
||||||
// false otherwise. If "binary" is false data is read
|
|
||||||
// using ifstream's text mode, otherwise data is read with
|
|
||||||
// no transcoding.
|
|
||||||
bool LoadFile(const char* name, bool binary, std::string* buf);
|
|
||||||
|
|
||||||
// Save data "buf" of length "len" bytes into a file
|
|
||||||
// "name" returning true if successful, false otherwise.
|
|
||||||
// If "binary" is false data is written using ifstream's
|
|
||||||
// text mode, otherwise data is written with no
|
|
||||||
// transcoding.
|
|
||||||
// NOTE: this function is deprecated in favor of FileSaver class,
|
|
||||||
// but left here for compatibility.
|
|
||||||
bool SaveFile(const char* name, const char* buf, size_t len, bool binary);
|
|
||||||
|
|
||||||
// Save data "buf" into file "name" returning true if
|
|
||||||
// successful, false otherwise. If "binary" is false
|
|
||||||
// data is written using ifstream's text mode, otherwise
|
|
||||||
// data is written with no transcoding.
|
|
||||||
// NOTE: this function is deprecated in favor of FileSaver class,
|
|
||||||
// but left here for compatibility.
|
|
||||||
inline bool SaveFile(const char* name, const std::string& buf, bool binary) {
|
|
||||||
return SaveFile(name, buf.c_str(), buf.size(), binary);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Functionality for minimalistic portable path handling.
|
|
||||||
|
|
||||||
// The functions below behave correctly regardless of whether posix ('/') or
|
|
||||||
// Windows ('/' or '\\') separators are used.
|
|
||||||
|
|
||||||
// Any new separators inserted are always posix.
|
|
||||||
FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
|
|
||||||
|
|
||||||
// Returns the path with the extension, if any, removed.
|
|
||||||
std::string StripExtension(const std::string& filepath);
|
|
||||||
|
|
||||||
// Returns the extension, if any.
|
|
||||||
std::string GetExtension(const std::string& filepath);
|
|
||||||
|
|
||||||
// Return the last component of the path, after the last separator.
|
|
||||||
std::string StripPath(const std::string& filepath);
|
|
||||||
|
|
||||||
// Strip the last component of the path + separator.
|
|
||||||
std::string StripFileName(const std::string& filepath);
|
|
||||||
|
|
||||||
std::string StripPrefix(const std::string& filepath,
|
|
||||||
const std::string& prefix_to_remove);
|
|
||||||
|
|
||||||
// Concatenates a path with a filename, regardless of whether the path
|
|
||||||
// ends in a separator or not.
|
|
||||||
std::string ConCatPathFileName(const std::string& path,
|
|
||||||
const std::string& filename);
|
|
||||||
|
|
||||||
// Replaces any '\\' separators with '/'
|
|
||||||
std::string PosixPath(const char* path);
|
|
||||||
std::string PosixPath(const std::string& path);
|
|
||||||
|
|
||||||
// This function ensure a directory exists, by recursively
|
|
||||||
// creating dirs for any parts of the path that don't exist yet.
|
|
||||||
void EnsureDirExists(const std::string& filepath);
|
|
||||||
|
|
||||||
// Obtains the relative or absolute path.
|
|
||||||
std::string FilePath(const std::string& project, const std::string& filePath,
|
|
||||||
bool absolute);
|
|
||||||
|
|
||||||
// Obtains the absolute path from any other path.
|
|
||||||
// Returns the input path if the absolute path couldn't be resolved.
|
|
||||||
std::string AbsolutePath(const std::string& filepath);
|
|
||||||
|
|
||||||
// Returns files relative to the --project_root path, prefixed with `//`.
|
|
||||||
std::string RelativeToRootPath(const std::string& project,
|
|
||||||
const std::string& filepath);
|
|
||||||
|
|
||||||
// To and from UTF-8 unicode conversion functions
|
|
||||||
|
|
||||||
// Convert a unicode code point into a UTF-8 representation by appending it
|
|
||||||
// to a string. Returns the number of bytes generated.
|
|
||||||
inline int ToUTF8(uint32_t ucc, std::string* out) {
|
|
||||||
FLATBUFFERS_ASSERT(!(ucc & 0x80000000)); // Top bit can't be set.
|
|
||||||
// 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
// Max bits this encoding can represent.
|
|
||||||
uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
|
|
||||||
if (ucc < (1u << max_bits)) { // does it fit?
|
|
||||||
// Remaining bits not encoded in the first byte, store 6 bits each
|
|
||||||
uint32_t remain_bits = i * 6;
|
|
||||||
// Store first byte:
|
|
||||||
(*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
|
|
||||||
(ucc >> remain_bits));
|
|
||||||
// Store remaining bytes:
|
|
||||||
for (int j = i - 1; j >= 0; j--) {
|
|
||||||
(*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
|
|
||||||
}
|
|
||||||
return i + 1; // Return the number of bytes added.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FLATBUFFERS_ASSERT(0); // Impossible to arrive here.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts whatever prefix of the incoming string corresponds to a valid
|
|
||||||
// UTF-8 sequence into a unicode code. The incoming pointer will have been
|
|
||||||
// advanced past all bytes parsed.
|
|
||||||
// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in
|
|
||||||
// this case).
|
|
||||||
inline int FromUTF8(const char** in) {
|
|
||||||
int len = 0;
|
|
||||||
// Count leading 1 bits.
|
|
||||||
for (int mask = 0x80; mask >= 0x04; mask >>= 1) {
|
|
||||||
if (**in & mask) {
|
|
||||||
len++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((static_cast<unsigned char>(**in) << len) & 0x80)
|
|
||||||
return -1; // Bit after leading 1's must be 0.
|
|
||||||
if (!len) return *(*in)++;
|
|
||||||
// UTF-8 encoded values with a length are between 2 and 4 bytes.
|
|
||||||
if (len < 2 || len > 4) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Grab initial bits of the code.
|
|
||||||
int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
|
|
||||||
for (int i = 0; i < len - 1; i++) {
|
|
||||||
if ((**in & 0xC0) != 0x80) return -1; // Upper bits must 1 0.
|
|
||||||
ucc <<= 6;
|
|
||||||
ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code.
|
|
||||||
}
|
|
||||||
// UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
|
|
||||||
// UTF-16 surrogate pairs).
|
|
||||||
if (ucc >= 0xD800 && ucc <= 0xDFFF) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// UTF-8 must represent code points in their shortest possible encoding.
|
|
||||||
switch (len) {
|
|
||||||
case 2:
|
|
||||||
// Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
|
|
||||||
if (ucc < 0x0080 || ucc > 0x07FF) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
// Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
|
|
||||||
if (ucc < 0x0800 || ucc > 0xFFFF) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
// Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
|
|
||||||
if (ucc < 0x10000 || ucc > 0x10FFFF) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ucc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
|
||||||
// Wraps a string to a maximum length, inserting new lines where necessary. Any
|
|
||||||
// existing whitespace will be collapsed down to a single space. A prefix or
|
|
||||||
// suffix can be provided, which will be inserted before or after a wrapped
|
|
||||||
// line, respectively.
|
|
||||||
inline std::string WordWrap(const std::string in, size_t max_length,
|
|
||||||
const std::string wrapped_line_prefix,
|
|
||||||
const std::string wrapped_line_suffix) {
|
|
||||||
std::istringstream in_stream(in);
|
|
||||||
std::string wrapped, line, word;
|
|
||||||
|
|
||||||
in_stream >> word;
|
|
||||||
line = word;
|
|
||||||
|
|
||||||
while (in_stream >> word) {
|
|
||||||
if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) <
|
|
||||||
max_length) {
|
|
||||||
line += " " + word;
|
|
||||||
} else {
|
|
||||||
wrapped += line + wrapped_line_suffix + "\n";
|
|
||||||
line = wrapped_line_prefix + word;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wrapped += line;
|
|
||||||
|
|
||||||
return wrapped;
|
|
||||||
}
|
|
||||||
#endif // !FLATBUFFERS_PREFER_PRINTF
|
|
||||||
|
|
||||||
inline bool EscapeString(const char* s, size_t length, std::string* _text,
|
|
||||||
bool allow_non_utf8, bool natural_utf8) {
|
|
||||||
std::string& text = *_text;
|
|
||||||
text += "\"";
|
|
||||||
for (uoffset_t i = 0; i < length; i++) {
|
|
||||||
char c = s[i];
|
|
||||||
switch (c) {
|
|
||||||
case '\n':
|
|
||||||
text += "\\n";
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
text += "\\t";
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
text += "\\r";
|
|
||||||
break;
|
|
||||||
case '\b':
|
|
||||||
text += "\\b";
|
|
||||||
break;
|
|
||||||
case '\f':
|
|
||||||
text += "\\f";
|
|
||||||
break;
|
|
||||||
case '\"':
|
|
||||||
text += "\\\"";
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
text += "\\\\";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (c >= ' ' && c <= '~') {
|
|
||||||
text += c;
|
|
||||||
} else {
|
|
||||||
// Not printable ASCII data. Let's see if it's valid UTF-8 first:
|
|
||||||
const char* utf8 = s + i;
|
|
||||||
int ucc = FromUTF8(&utf8);
|
|
||||||
if (ucc < 0) {
|
|
||||||
if (allow_non_utf8) {
|
|
||||||
text += "\\x";
|
|
||||||
text += IntToStringHex(static_cast<uint8_t>(c), 2);
|
|
||||||
} else {
|
|
||||||
// There are two cases here:
|
|
||||||
//
|
|
||||||
// 1) We reached here by parsing an IDL file. In that case,
|
|
||||||
// we previously checked for non-UTF-8, so we shouldn't reach
|
|
||||||
// here.
|
|
||||||
//
|
|
||||||
// 2) We reached here by someone calling GenText()
|
|
||||||
// on a previously-serialized flatbuffer. The data might have
|
|
||||||
// non-UTF-8 Strings, or might be corrupt.
|
|
||||||
//
|
|
||||||
// In both cases, we have to give up and inform the caller
|
|
||||||
// they have no JSON.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (natural_utf8) {
|
|
||||||
// utf8 points to past all utf-8 bytes parsed
|
|
||||||
text.append(s + i, static_cast<size_t>(utf8 - s - i));
|
|
||||||
} else if (ucc <= 0xFFFF) {
|
|
||||||
// Parses as Unicode within JSON's \uXXXX range, so use that.
|
|
||||||
text += "\\u";
|
|
||||||
text += IntToStringHex(ucc, 4);
|
|
||||||
} else if (ucc <= 0x10FFFF) {
|
|
||||||
// Encode Unicode SMP values to a surrogate pair using two \u
|
|
||||||
// escapes.
|
|
||||||
uint32_t base = ucc - 0x10000;
|
|
||||||
auto high_surrogate = (base >> 10) + 0xD800;
|
|
||||||
auto low_surrogate = (base & 0x03FF) + 0xDC00;
|
|
||||||
text += "\\u";
|
|
||||||
text += IntToStringHex(high_surrogate, 4);
|
|
||||||
text += "\\u";
|
|
||||||
text += IntToStringHex(low_surrogate, 4);
|
|
||||||
}
|
|
||||||
// Skip past characters recognized.
|
|
||||||
i = static_cast<uoffset_t>(utf8 - s - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text += "\"";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string BufferToHexText(const void* buffer, size_t buffer_size,
|
|
||||||
size_t max_length,
|
|
||||||
const std::string& wrapped_line_prefix,
|
|
||||||
const std::string& wrapped_line_suffix) {
|
|
||||||
std::string text = wrapped_line_prefix;
|
|
||||||
size_t start_offset = 0;
|
|
||||||
const char* s = reinterpret_cast<const char*>(buffer);
|
|
||||||
for (size_t i = 0; s && i < buffer_size; i++) {
|
|
||||||
// Last iteration or do we have more?
|
|
||||||
bool have_more = i + 1 < buffer_size;
|
|
||||||
text += "0x";
|
|
||||||
text += IntToStringHex(static_cast<uint8_t>(s[i]), 2);
|
|
||||||
if (have_more) {
|
|
||||||
text += ',';
|
|
||||||
}
|
|
||||||
// If we have more to process and we reached max_length
|
|
||||||
if (have_more &&
|
|
||||||
text.size() + wrapped_line_suffix.size() >= start_offset + max_length) {
|
|
||||||
text += wrapped_line_suffix;
|
|
||||||
text += '\n';
|
|
||||||
start_offset = text.size();
|
|
||||||
text += wrapped_line_prefix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text += wrapped_line_suffix;
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove paired quotes in a string: "text"|'text' -> text.
|
|
||||||
std::string RemoveStringQuotes(const std::string& s);
|
|
||||||
|
|
||||||
// Change th global C-locale to locale with name <locale_name>.
|
|
||||||
// Returns an actual locale name in <_value>, useful if locale_name is "" or
|
|
||||||
// null.
|
|
||||||
bool SetGlobalTestLocale(const char* locale_name,
|
|
||||||
std::string* _value = nullptr);
|
|
||||||
|
|
||||||
// Read (or test) a value of environment variable.
|
|
||||||
bool ReadEnvironmentVariable(const char* var_name,
|
|
||||||
std::string* _value = nullptr);
|
|
||||||
|
|
||||||
enum class Case {
|
|
||||||
kUnknown = 0,
|
|
||||||
// TheQuickBrownFox
|
|
||||||
kUpperCamel = 1,
|
|
||||||
// theQuickBrownFox
|
|
||||||
kLowerCamel = 2,
|
|
||||||
// the_quick_brown_fox
|
|
||||||
kSnake = 3,
|
|
||||||
// THE_QUICK_BROWN_FOX
|
|
||||||
kScreamingSnake = 4,
|
|
||||||
// THEQUICKBROWNFOX
|
|
||||||
kAllUpper = 5,
|
|
||||||
// thequickbrownfox
|
|
||||||
kAllLower = 6,
|
|
||||||
// the-quick-brown-fox
|
|
||||||
kDasher = 7,
|
|
||||||
// THEQuiCKBr_ownFox (or whatever you want, we won't change it)
|
|
||||||
kKeep = 8,
|
|
||||||
// the_quick_brown_fox123 (as opposed to the_quick_brown_fox_123)
|
|
||||||
kSnake2 = 9,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Convert the `input` string of case `input_case` to the specified
|
|
||||||
// `output_case`.
|
|
||||||
std::string ConvertCase(const std::string& input, Case output_case,
|
|
||||||
Case input_case = Case::kSnake);
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_UTIL_H_
|
|
||||||
@@ -1,455 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_VECTOR_H_
|
|
||||||
#define FLATBUFFERS_VECTOR_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/buffer.h"
|
|
||||||
#include "flatbuffers/stl_emulation.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
struct String;
|
|
||||||
|
|
||||||
// An STL compatible iterator implementation for Vector below, effectively
|
|
||||||
// calling Get() for every element.
|
|
||||||
template <typename T, typename IT, typename Data = uint8_t*,
|
|
||||||
typename SizeT = uoffset_t>
|
|
||||||
struct VectorIterator {
|
|
||||||
typedef std::random_access_iterator_tag iterator_category;
|
|
||||||
typedef IT value_type;
|
|
||||||
typedef ptrdiff_t difference_type;
|
|
||||||
typedef IT* pointer;
|
|
||||||
typedef IT& reference;
|
|
||||||
|
|
||||||
static const SizeT element_stride = IndirectHelper<T>::element_stride;
|
|
||||||
|
|
||||||
VectorIterator(Data data, SizeT i) : data_(data + element_stride * i) {}
|
|
||||||
VectorIterator(const VectorIterator& other) : data_(other.data_) {}
|
|
||||||
VectorIterator() : data_(nullptr) {}
|
|
||||||
|
|
||||||
VectorIterator& operator=(const VectorIterator& other) {
|
|
||||||
data_ = other.data_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorIterator& operator=(VectorIterator&& other) {
|
|
||||||
data_ = other.data_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const VectorIterator& other) const {
|
|
||||||
return data_ == other.data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const VectorIterator& other) const {
|
|
||||||
return data_ != other.data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const VectorIterator& other) const {
|
|
||||||
return data_ < other.data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator>(const VectorIterator& other) const {
|
|
||||||
return data_ > other.data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<=(const VectorIterator& other) const {
|
|
||||||
return !(data_ > other.data_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator>=(const VectorIterator& other) const {
|
|
||||||
return !(data_ < other.data_);
|
|
||||||
}
|
|
||||||
|
|
||||||
difference_type operator-(const VectorIterator& other) const {
|
|
||||||
return (data_ - other.data_) / element_stride;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: return type is incompatible with the standard
|
|
||||||
// `reference operator*()`.
|
|
||||||
IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
|
|
||||||
|
|
||||||
// Note: return type is incompatible with the standard
|
|
||||||
// `pointer operator->()`.
|
|
||||||
IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
|
|
||||||
|
|
||||||
VectorIterator& operator++() {
|
|
||||||
data_ += element_stride;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorIterator operator++(int) {
|
|
||||||
VectorIterator temp(data_, 0);
|
|
||||||
data_ += element_stride;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorIterator operator+(const SizeT& offset) const {
|
|
||||||
return VectorIterator(data_ + offset * element_stride, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorIterator& operator+=(const SizeT& offset) {
|
|
||||||
data_ += offset * element_stride;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorIterator& operator--() {
|
|
||||||
data_ -= element_stride;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorIterator operator--(int) {
|
|
||||||
VectorIterator temp(data_, 0);
|
|
||||||
data_ -= element_stride;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorIterator operator-(const SizeT& offset) const {
|
|
||||||
return VectorIterator(data_ - offset * element_stride, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorIterator& operator-=(const SizeT& offset) {
|
|
||||||
data_ -= offset * element_stride;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Data data_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename IT, typename SizeT = uoffset_t>
|
|
||||||
using VectorConstIterator = VectorIterator<T, IT, const uint8_t*, SizeT>;
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
|
||||||
explicit VectorReverseIterator(Iterator iter)
|
|
||||||
: std::reverse_iterator<Iterator>(iter) {}
|
|
||||||
|
|
||||||
// Note: return type is incompatible with the standard
|
|
||||||
// `reference operator*()`.
|
|
||||||
typename Iterator::value_type operator*() const {
|
|
||||||
auto tmp = std::reverse_iterator<Iterator>::current;
|
|
||||||
return *--tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: return type is incompatible with the standard
|
|
||||||
// `pointer operator->()`.
|
|
||||||
typename Iterator::value_type operator->() const {
|
|
||||||
auto tmp = std::reverse_iterator<Iterator>::current;
|
|
||||||
return *--tmp;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is used as a helper type for accessing vectors.
|
|
||||||
// Vector::data() assumes the vector elements start after the length field.
|
|
||||||
template <typename T, typename SizeT = uoffset_t>
|
|
||||||
class Vector {
|
|
||||||
public:
|
|
||||||
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type,
|
|
||||||
uint8_t*, SizeT>
|
|
||||||
iterator;
|
|
||||||
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type, SizeT>
|
|
||||||
const_iterator;
|
|
||||||
typedef VectorReverseIterator<iterator> reverse_iterator;
|
|
||||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
|
||||||
|
|
||||||
typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
|
|
||||||
scalar_tag;
|
|
||||||
|
|
||||||
static FLATBUFFERS_CONSTEXPR bool is_span_observable =
|
|
||||||
scalar_tag::value && !std::is_pointer<T>::value &&
|
|
||||||
(FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1);
|
|
||||||
|
|
||||||
SizeT size() const { return EndianScalar(length_); }
|
|
||||||
|
|
||||||
// Returns true if the vector is empty.
|
|
||||||
//
|
|
||||||
// This just provides another standardized method that is expected of vectors.
|
|
||||||
bool empty() const { return size() == 0; }
|
|
||||||
|
|
||||||
// Deprecated: use size(). Here for backwards compatibility.
|
|
||||||
FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]])
|
|
||||||
SizeT Length() const { return size(); }
|
|
||||||
|
|
||||||
typedef SizeT size_type;
|
|
||||||
typedef typename IndirectHelper<T>::return_type return_type;
|
|
||||||
typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
|
|
||||||
typedef return_type value_type;
|
|
||||||
|
|
||||||
return_type Get(SizeT i) const {
|
|
||||||
FLATBUFFERS_ASSERT(i < size());
|
|
||||||
return IndirectHelper<T>::Read(Data(), i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return_type operator[](SizeT i) const { return Get(i); }
|
|
||||||
|
|
||||||
// If this is a Vector of enums, T will be its storage type, not the enum
|
|
||||||
// type. This function makes it convenient to retrieve value with enum
|
|
||||||
// type E.
|
|
||||||
template <typename E>
|
|
||||||
E GetEnum(SizeT i) const {
|
|
||||||
return static_cast<E>(Get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this a vector of unions, this does the cast for you. There's no check
|
|
||||||
// to make sure this is the right type!
|
|
||||||
template <typename U>
|
|
||||||
const U* GetAs(SizeT i) const {
|
|
||||||
return reinterpret_cast<const U*>(Get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this a vector of unions, this does the cast for you. There's no check
|
|
||||||
// to make sure this is actually a string!
|
|
||||||
const String* GetAsString(SizeT i) const {
|
|
||||||
return reinterpret_cast<const String*>(Get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
const void* GetStructFromOffset(size_t o) const {
|
|
||||||
return reinterpret_cast<const void*>(Data() + o);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator begin() { return iterator(Data(), 0); }
|
|
||||||
const_iterator begin() const { return const_iterator(Data(), 0); }
|
|
||||||
|
|
||||||
iterator end() { return iterator(Data(), size()); }
|
|
||||||
const_iterator end() const { return const_iterator(Data(), size()); }
|
|
||||||
|
|
||||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
|
||||||
const_reverse_iterator rbegin() const {
|
|
||||||
return const_reverse_iterator(end());
|
|
||||||
}
|
|
||||||
|
|
||||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
|
||||||
const_reverse_iterator rend() const {
|
|
||||||
return const_reverse_iterator(begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator cbegin() const { return begin(); }
|
|
||||||
|
|
||||||
const_iterator cend() const { return end(); }
|
|
||||||
|
|
||||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
|
||||||
|
|
||||||
const_reverse_iterator crend() const { return rend(); }
|
|
||||||
|
|
||||||
// Change elements if you have a non-const pointer to this object.
|
|
||||||
// Scalars only. See reflection.h, and the documentation.
|
|
||||||
void Mutate(SizeT i, const T& val) {
|
|
||||||
FLATBUFFERS_ASSERT(i < size());
|
|
||||||
WriteScalar(data() + i, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change an element of a vector of tables (or strings).
|
|
||||||
// "val" points to the new table/string, as you can obtain from
|
|
||||||
// e.g. reflection::AddFlatBuffer().
|
|
||||||
void MutateOffset(SizeT i, const uint8_t* val) {
|
|
||||||
FLATBUFFERS_ASSERT(i < size());
|
|
||||||
static_assert(sizeof(T) == sizeof(SizeT), "Unrelated types");
|
|
||||||
WriteScalar(data() + i,
|
|
||||||
static_cast<SizeT>(val - (Data() + i * sizeof(SizeT))));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a mutable pointer to tables/strings inside this vector.
|
|
||||||
mutable_return_type GetMutableObject(SizeT i) const {
|
|
||||||
FLATBUFFERS_ASSERT(i < size());
|
|
||||||
return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The raw data in little endian format. Use with care.
|
|
||||||
const uint8_t* Data() const {
|
|
||||||
return reinterpret_cast<const uint8_t*>(&length_ + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* Data() { return reinterpret_cast<uint8_t*>(&length_ + 1); }
|
|
||||||
|
|
||||||
// Similarly, but typed, much like std::vector::data
|
|
||||||
const T* data() const { return reinterpret_cast<const T*>(Data()); }
|
|
||||||
T* data() { return reinterpret_cast<T*>(Data()); }
|
|
||||||
|
|
||||||
template <typename K>
|
|
||||||
return_type LookupByKey(K key) const {
|
|
||||||
void* search_result = std::bsearch(
|
|
||||||
&key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
|
|
||||||
|
|
||||||
if (!search_result) {
|
|
||||||
return nullptr; // Key not found.
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t* element = reinterpret_cast<const uint8_t*>(search_result);
|
|
||||||
|
|
||||||
return IndirectHelper<T>::Read(element, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename K>
|
|
||||||
mutable_return_type MutableLookupByKey(K key) {
|
|
||||||
return const_cast<mutable_return_type>(LookupByKey(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// This class is only used to access pre-existing data. Don't ever
|
|
||||||
// try to construct these manually.
|
|
||||||
Vector();
|
|
||||||
|
|
||||||
SizeT length_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// This class is a pointer. Copying will therefore create an invalid object.
|
|
||||||
// Private and unimplemented copy constructor.
|
|
||||||
Vector(const Vector&);
|
|
||||||
Vector& operator=(const Vector&);
|
|
||||||
|
|
||||||
template <typename K>
|
|
||||||
static int KeyCompare(const void* ap, const void* bp) {
|
|
||||||
const K* key = reinterpret_cast<const K*>(ap);
|
|
||||||
const uint8_t* data = reinterpret_cast<const uint8_t*>(bp);
|
|
||||||
auto table = IndirectHelper<T>::Read(data, 0);
|
|
||||||
|
|
||||||
// std::bsearch compares with the operands transposed, so we negate the
|
|
||||||
// result here.
|
|
||||||
return -table->KeyCompareWithValue(*key);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using Vector64 = Vector<T, uoffset64_t>;
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U>& vec)
|
|
||||||
FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(Vector<U>::is_span_observable,
|
|
||||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
|
||||||
return span<U>(vec.data(), vec.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
|
|
||||||
const Vector<U>& vec) FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(Vector<U>::is_span_observable,
|
|
||||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
|
||||||
return span<const U>(vec.data(), vec.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t> make_bytes_span(
|
|
||||||
Vector<U>& vec) FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(Vector<U>::scalar_tag::value,
|
|
||||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
|
||||||
return span<uint8_t>(vec.Data(), vec.size() * sizeof(U));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
|
|
||||||
const Vector<U>& vec) FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(Vector<U>::scalar_tag::value,
|
|
||||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
|
||||||
return span<const uint8_t>(vec.Data(), vec.size() * sizeof(U));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FLATBUFFERS_LITTLEENDIAN
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_structs_span(
|
|
||||||
Vector<const U*>& vec) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return span<U>(reinterpret_cast<U*>(vec.data()), vec.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_structs_span(
|
|
||||||
const Vector<const U*>& vec) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return span<const U>(reinterpret_cast<const U*>(vec.data()), vec.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Convenient helper functions to get a span of any vector, regardless
|
|
||||||
// of whether it is null or not (the field is not set).
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U>* ptr)
|
|
||||||
FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(Vector<U>::is_span_observable,
|
|
||||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
|
||||||
return ptr ? make_span(*ptr) : span<U>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
|
|
||||||
const Vector<U>* ptr) FLATBUFFERS_NOEXCEPT {
|
|
||||||
static_assert(Vector<U>::is_span_observable,
|
|
||||||
"wrong type U, only LE-scalar, or byte types are allowed");
|
|
||||||
return ptr ? make_span(*ptr) : span<const U>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FLATBUFFERS_LITTLEENDIAN
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_structs_span(
|
|
||||||
Vector<const U*>* ptr) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return ptr ? make_span(*ptr) : span<U>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_structs_span(
|
|
||||||
const Vector<const U*>* ptr) FLATBUFFERS_NOEXCEPT {
|
|
||||||
return ptr ? make_span(*ptr) : span<const U>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Represent a vector much like the template above, but in this case we
|
|
||||||
// don't know what the element types are (used with reflection.h).
|
|
||||||
class VectorOfAny {
|
|
||||||
public:
|
|
||||||
uoffset_t size() const { return EndianScalar(length_); }
|
|
||||||
|
|
||||||
const uint8_t* Data() const {
|
|
||||||
return reinterpret_cast<const uint8_t*>(&length_ + 1);
|
|
||||||
}
|
|
||||||
uint8_t* Data() { return reinterpret_cast<uint8_t*>(&length_ + 1); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
VectorOfAny();
|
|
||||||
|
|
||||||
uoffset_t length_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
VectorOfAny(const VectorOfAny&);
|
|
||||||
VectorOfAny& operator=(const VectorOfAny&);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename U>
|
|
||||||
Vector<Offset<T>>* VectorCast(Vector<Offset<U>>* ptr) {
|
|
||||||
static_assert(std::is_base_of<T, U>::value, "Unrelated types");
|
|
||||||
return reinterpret_cast<Vector<Offset<T>>*>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename U>
|
|
||||||
const Vector<Offset<T>>* VectorCast(const Vector<Offset<U>>* ptr) {
|
|
||||||
static_assert(std::is_base_of<T, U>::value, "Unrelated types");
|
|
||||||
return reinterpret_cast<const Vector<Offset<T>>*>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convenient helper function to get the length of any vector, regardless
|
|
||||||
// of whether it is null or not (the field is not set).
|
|
||||||
template <typename T>
|
|
||||||
static inline size_t VectorLength(const Vector<T>* v) {
|
|
||||||
return v ? v->size() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_VERIFIER_H_
|
|
||||||
@@ -1,298 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_
|
|
||||||
#define FLATBUFFERS_VECTOR_DOWNWARD_H_
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/default_allocator.h"
|
|
||||||
#include "flatbuffers/detached_buffer.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// This is a minimal replication of std::vector<uint8_t> functionality,
|
|
||||||
// except growing from higher to lower addresses. i.e. push_back() inserts data
|
|
||||||
// in the lowest address in the vector.
|
|
||||||
// Since this vector leaves the lower part unused, we support a "scratch-pad"
|
|
||||||
// that can be stored there for temporary data, to share the allocated space.
|
|
||||||
// Essentially, this supports 2 std::vectors in a single buffer.
|
|
||||||
template <typename SizeT = uoffset_t>
|
|
||||||
class vector_downward {
|
|
||||||
public:
|
|
||||||
explicit vector_downward(size_t initial_size, Allocator* allocator,
|
|
||||||
bool own_allocator, size_t buffer_minalign,
|
|
||||||
const SizeT max_size = FLATBUFFERS_MAX_BUFFER_SIZE)
|
|
||||||
: allocator_(allocator),
|
|
||||||
own_allocator_(own_allocator),
|
|
||||||
initial_size_(initial_size),
|
|
||||||
max_size_(max_size),
|
|
||||||
buffer_minalign_(buffer_minalign),
|
|
||||||
reserved_(0),
|
|
||||||
size_(0),
|
|
||||||
buf_(nullptr),
|
|
||||||
cur_(nullptr),
|
|
||||||
scratch_(nullptr) {}
|
|
||||||
|
|
||||||
vector_downward(vector_downward&& other) noexcept
|
|
||||||
// clang-format on
|
|
||||||
: allocator_(other.allocator_),
|
|
||||||
own_allocator_(other.own_allocator_),
|
|
||||||
initial_size_(other.initial_size_),
|
|
||||||
max_size_(other.max_size_),
|
|
||||||
buffer_minalign_(other.buffer_minalign_),
|
|
||||||
reserved_(other.reserved_),
|
|
||||||
size_(other.size_),
|
|
||||||
buf_(other.buf_),
|
|
||||||
cur_(other.cur_),
|
|
||||||
scratch_(other.scratch_) {
|
|
||||||
// No change in other.allocator_
|
|
||||||
// No change in other.initial_size_
|
|
||||||
// No change in other.buffer_minalign_
|
|
||||||
other.own_allocator_ = false;
|
|
||||||
other.reserved_ = 0;
|
|
||||||
other.buf_ = nullptr;
|
|
||||||
other.cur_ = nullptr;
|
|
||||||
other.scratch_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector_downward& operator=(vector_downward&& other) noexcept {
|
|
||||||
// Move construct a temporary and swap idiom
|
|
||||||
vector_downward temp(std::move(other));
|
|
||||||
swap(temp);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~vector_downward() {
|
|
||||||
clear_buffer();
|
|
||||||
clear_allocator();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
clear_buffer();
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
if (buf_) {
|
|
||||||
cur_ = buf_ + reserved_;
|
|
||||||
} else {
|
|
||||||
reserved_ = 0;
|
|
||||||
cur_ = nullptr;
|
|
||||||
}
|
|
||||||
size_ = 0;
|
|
||||||
clear_scratch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_scratch() { scratch_ = buf_; }
|
|
||||||
|
|
||||||
void clear_allocator() {
|
|
||||||
if (own_allocator_ && allocator_) {
|
|
||||||
delete allocator_;
|
|
||||||
}
|
|
||||||
allocator_ = nullptr;
|
|
||||||
own_allocator_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_buffer() {
|
|
||||||
if (buf_) Deallocate(allocator_, buf_, reserved_);
|
|
||||||
buf_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relinquish the pointer to the caller.
|
|
||||||
uint8_t* release_raw(size_t& allocated_bytes, size_t& offset) {
|
|
||||||
auto* buf = buf_;
|
|
||||||
allocated_bytes = reserved_;
|
|
||||||
offset = vector_downward::offset();
|
|
||||||
|
|
||||||
// release_raw only relinquishes the buffer ownership.
|
|
||||||
// Does not deallocate or reset the allocator. Destructor will do that.
|
|
||||||
buf_ = nullptr;
|
|
||||||
clear();
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relinquish the pointer to the caller.
|
|
||||||
DetachedBuffer release() {
|
|
||||||
// allocator ownership (if any) is transferred to DetachedBuffer.
|
|
||||||
DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
|
|
||||||
size());
|
|
||||||
if (own_allocator_) {
|
|
||||||
allocator_ = nullptr;
|
|
||||||
own_allocator_ = false;
|
|
||||||
}
|
|
||||||
buf_ = nullptr;
|
|
||||||
clear();
|
|
||||||
return fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ensure_space(size_t len) {
|
|
||||||
FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
|
|
||||||
// If the length is larger than the unused part of the buffer, we need to
|
|
||||||
// grow.
|
|
||||||
if (len > unused_buffer_size()) {
|
|
||||||
reallocate(len);
|
|
||||||
}
|
|
||||||
FLATBUFFERS_ASSERT(size() < max_size_);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t* make_space(size_t len) {
|
|
||||||
if (len) {
|
|
||||||
ensure_space(len);
|
|
||||||
cur_ -= len;
|
|
||||||
size_ += static_cast<SizeT>(len);
|
|
||||||
}
|
|
||||||
return cur_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns nullptr if using the DefaultAllocator.
|
|
||||||
Allocator* get_custom_allocator() { return allocator_; }
|
|
||||||
|
|
||||||
// The current offset into the buffer.
|
|
||||||
size_t offset() const { return cur_ - buf_; }
|
|
||||||
|
|
||||||
// The total size of the vector (both the buffer and scratch parts).
|
|
||||||
inline SizeT size() const { return size_; }
|
|
||||||
|
|
||||||
// The size of the buffer part of the vector that is currently unused.
|
|
||||||
SizeT unused_buffer_size() const {
|
|
||||||
return static_cast<SizeT>(cur_ - scratch_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The size of the scratch part of the vector.
|
|
||||||
SizeT scratch_size() const { return static_cast<SizeT>(scratch_ - buf_); }
|
|
||||||
|
|
||||||
size_t capacity() const { return reserved_; }
|
|
||||||
|
|
||||||
uint8_t* data() const {
|
|
||||||
FLATBUFFERS_ASSERT(cur_);
|
|
||||||
return cur_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* scratch_data() const {
|
|
||||||
FLATBUFFERS_ASSERT(buf_);
|
|
||||||
return buf_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* scratch_end() const {
|
|
||||||
FLATBUFFERS_ASSERT(scratch_);
|
|
||||||
return scratch_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* data_at(size_t offset) const { return buf_ + reserved_ - offset; }
|
|
||||||
|
|
||||||
void push(const uint8_t* bytes, size_t num) {
|
|
||||||
if (num > 0) {
|
|
||||||
memcpy(make_space(num), bytes, num);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specialized version of push() that avoids memcpy call for small data.
|
|
||||||
template <typename T>
|
|
||||||
void push_small(const T& little_endian_t) {
|
|
||||||
make_space(sizeof(T));
|
|
||||||
*reinterpret_cast<T*>(cur_) = little_endian_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void scratch_push_small(const T& t) {
|
|
||||||
ensure_space(sizeof(T));
|
|
||||||
*reinterpret_cast<T*>(scratch_) = t;
|
|
||||||
scratch_ += sizeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill() is most frequently called with small byte counts (<= 4),
|
|
||||||
// which is why we're using loops rather than calling memset.
|
|
||||||
void fill(size_t zero_pad_bytes) {
|
|
||||||
make_space(zero_pad_bytes);
|
|
||||||
for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version for when we know the size is larger.
|
|
||||||
// Precondition: zero_pad_bytes > 0
|
|
||||||
void fill_big(size_t zero_pad_bytes) {
|
|
||||||
memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop(size_t bytes_to_remove) {
|
|
||||||
cur_ += bytes_to_remove;
|
|
||||||
size_ -= static_cast<SizeT>(bytes_to_remove);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
|
|
||||||
|
|
||||||
void swap(vector_downward& other) {
|
|
||||||
using std::swap;
|
|
||||||
swap(allocator_, other.allocator_);
|
|
||||||
swap(own_allocator_, other.own_allocator_);
|
|
||||||
swap(initial_size_, other.initial_size_);
|
|
||||||
swap(buffer_minalign_, other.buffer_minalign_);
|
|
||||||
swap(reserved_, other.reserved_);
|
|
||||||
swap(size_, other.size_);
|
|
||||||
swap(max_size_, other.max_size_);
|
|
||||||
swap(buf_, other.buf_);
|
|
||||||
swap(cur_, other.cur_);
|
|
||||||
swap(scratch_, other.scratch_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap_allocator(vector_downward& other) {
|
|
||||||
using std::swap;
|
|
||||||
swap(allocator_, other.allocator_);
|
|
||||||
swap(own_allocator_, other.own_allocator_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// You shouldn't really be copying instances of this class.
|
|
||||||
FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward&));
|
|
||||||
FLATBUFFERS_DELETE_FUNC(vector_downward& operator=(const vector_downward&));
|
|
||||||
|
|
||||||
Allocator* allocator_;
|
|
||||||
bool own_allocator_;
|
|
||||||
size_t initial_size_;
|
|
||||||
|
|
||||||
// The maximum size the vector can be.
|
|
||||||
SizeT max_size_;
|
|
||||||
size_t buffer_minalign_;
|
|
||||||
size_t reserved_;
|
|
||||||
SizeT size_;
|
|
||||||
uint8_t* buf_;
|
|
||||||
uint8_t* cur_; // Points at location between empty (below) and used (above).
|
|
||||||
uint8_t* scratch_; // Points to the end of the scratchpad in use.
|
|
||||||
|
|
||||||
void reallocate(size_t len) {
|
|
||||||
auto old_reserved = reserved_;
|
|
||||||
auto old_size = size();
|
|
||||||
auto old_scratch_size = scratch_size();
|
|
||||||
reserved_ +=
|
|
||||||
(std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
|
|
||||||
reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
|
|
||||||
if (buf_) {
|
|
||||||
buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
|
|
||||||
old_size, old_scratch_size);
|
|
||||||
} else {
|
|
||||||
buf_ = Allocate(allocator_, reserved_);
|
|
||||||
}
|
|
||||||
cur_ = buf_ + reserved_ - old_size;
|
|
||||||
scratch_ = buf_ + old_scratch_size;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_VECTOR_DOWNWARD_H_
|
|
||||||
@@ -1,370 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_VERIFIER_H_
|
|
||||||
#define FLATBUFFERS_VERIFIER_H_
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
#include "flatbuffers/vector.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
// Helper class to verify the integrity of a FlatBuffer
|
|
||||||
template <bool TrackVerifierBufferSize>
|
|
||||||
class VerifierTemplate FLATBUFFERS_FINAL_CLASS {
|
|
||||||
public:
|
|
||||||
struct Options {
|
|
||||||
// The maximum nesting of tables and vectors before we call it invalid.
|
|
||||||
uoffset_t max_depth = 64;
|
|
||||||
// The maximum number of tables we will verify before we call it invalid.
|
|
||||||
uoffset_t max_tables = 1000000;
|
|
||||||
// If true, verify all data is aligned.
|
|
||||||
bool check_alignment = true;
|
|
||||||
// If true, run verifier on nested flatbuffers
|
|
||||||
bool check_nested_flatbuffers = true;
|
|
||||||
// The maximum size of a buffer.
|
|
||||||
size_t max_size = FLATBUFFERS_MAX_BUFFER_SIZE;
|
|
||||||
// Use assertions to check for errors.
|
|
||||||
bool assert = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit VerifierTemplate(const uint8_t* const buf, const size_t buf_len,
|
|
||||||
const Options& opts)
|
|
||||||
: buf_(buf), size_(buf_len), opts_(opts) {
|
|
||||||
FLATBUFFERS_ASSERT(size_ < opts.max_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated API, please construct with VerifierTemplate::Options.
|
|
||||||
VerifierTemplate(const uint8_t* const buf, const size_t buf_len,
|
|
||||||
const uoffset_t max_depth = 64,
|
|
||||||
const uoffset_t max_tables = 1000000,
|
|
||||||
const bool check_alignment = true)
|
|
||||||
: VerifierTemplate(buf, buf_len, [&] {
|
|
||||||
Options opts;
|
|
||||||
opts.max_depth = max_depth;
|
|
||||||
opts.max_tables = max_tables;
|
|
||||||
opts.check_alignment = check_alignment;
|
|
||||||
return opts;
|
|
||||||
}()) {}
|
|
||||||
|
|
||||||
// Central location where any verification failures register.
|
|
||||||
bool Check(const bool ok) const {
|
|
||||||
// clang-format off
|
|
||||||
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
|
|
||||||
if (opts_.assert) { FLATBUFFERS_ASSERT(ok); }
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
|
||||||
if (TrackVerifierBufferSize) {
|
|
||||||
if (!ok) {
|
|
||||||
upper_bound_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify any range within the buffer.
|
|
||||||
bool Verify(const size_t elem, const size_t elem_len) const {
|
|
||||||
if (TrackVerifierBufferSize) {
|
|
||||||
auto upper_bound = elem + elem_len;
|
|
||||||
if (upper_bound_ < upper_bound) {
|
|
||||||
upper_bound_ = upper_bound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Check(elem_len < size_ && elem <= size_ - elem_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VerifyAlignment(const size_t elem, const size_t align) const {
|
|
||||||
return Check((elem & (align - 1)) == 0 || !opts_.check_alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify a range indicated by sizeof(T).
|
|
||||||
template <typename T>
|
|
||||||
bool Verify(const size_t elem) const {
|
|
||||||
return VerifyAlignment(elem, sizeof(T)) && Verify(elem, sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VerifyFromPointer(const uint8_t* const p, const size_t len) {
|
|
||||||
return Verify(static_cast<size_t>(p - buf_), len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify relative to a known-good base pointer.
|
|
||||||
bool VerifyFieldStruct(const uint8_t* const base, const voffset_t elem_off,
|
|
||||||
const size_t elem_len, const size_t align) const {
|
|
||||||
const auto f = static_cast<size_t>(base - buf_) + elem_off;
|
|
||||||
return VerifyAlignment(f, align) && Verify(f, elem_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool VerifyField(const uint8_t* const base, const voffset_t elem_off,
|
|
||||||
const size_t align) const {
|
|
||||||
const auto f = static_cast<size_t>(base - buf_) + elem_off;
|
|
||||||
return VerifyAlignment(f, align) && Verify(f, sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify a pointer (may be NULL) of a table type.
|
|
||||||
template <typename T>
|
|
||||||
bool VerifyTable(const T* const table) {
|
|
||||||
return !table || table->Verify(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify a pointer (may be NULL) of any vector type.
|
|
||||||
template <int&..., typename T, typename LenT>
|
|
||||||
bool VerifyVector(const Vector<T, LenT>* const vec) const {
|
|
||||||
return !vec || VerifyVectorOrString<LenT>(
|
|
||||||
reinterpret_cast<const uint8_t*>(vec), sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify a pointer (may be NULL) of a vector to struct.
|
|
||||||
template <int&..., typename T, typename LenT>
|
|
||||||
bool VerifyVector(const Vector<const T*, LenT>* const vec) const {
|
|
||||||
return VerifyVector(reinterpret_cast<const Vector<T, LenT>*>(vec));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify a pointer (may be NULL) to string.
|
|
||||||
bool VerifyString(const String* const str) const {
|
|
||||||
size_t end;
|
|
||||||
return !str || (VerifyVectorOrString<uoffset_t>(
|
|
||||||
reinterpret_cast<const uint8_t*>(str), 1, &end) &&
|
|
||||||
Verify(end, 1) && // Must have terminator
|
|
||||||
Check(buf_[end] == '\0')); // Terminating byte must be 0.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common code between vectors and strings.
|
|
||||||
template <typename LenT = uoffset_t>
|
|
||||||
bool VerifyVectorOrString(const uint8_t* const vec, const size_t elem_size,
|
|
||||||
size_t* const end = nullptr) const {
|
|
||||||
const auto vec_offset = static_cast<size_t>(vec - buf_);
|
|
||||||
// Check we can read the size field.
|
|
||||||
if (!Verify<LenT>(vec_offset)) return false;
|
|
||||||
// Check the whole array. If this is a string, the byte past the array must
|
|
||||||
// be 0.
|
|
||||||
const LenT size = ReadScalar<LenT>(vec);
|
|
||||||
const auto max_elems = opts_.max_size / elem_size;
|
|
||||||
if (!Check(size < max_elems))
|
|
||||||
return false; // Protect against byte_size overflowing.
|
|
||||||
const auto byte_size = sizeof(LenT) + elem_size * size;
|
|
||||||
if (end) *end = vec_offset + byte_size;
|
|
||||||
return Verify(vec_offset, byte_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case for string contents, after the above has been called.
|
|
||||||
bool VerifyVectorOfStrings(const Vector<Offset<String>>* const vec) const {
|
|
||||||
if (vec) {
|
|
||||||
for (uoffset_t i = 0; i < vec->size(); i++) {
|
|
||||||
if (!VerifyString(vec->Get(i))) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case for table contents, after the above has been called.
|
|
||||||
template <typename T>
|
|
||||||
bool VerifyVectorOfTables(const Vector<Offset<T>>* const vec) {
|
|
||||||
if (vec) {
|
|
||||||
for (uoffset_t i = 0; i < vec->size(); i++) {
|
|
||||||
if (!vec->Get(i)->Verify(*this)) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FLATBUFFERS_SUPPRESS_UBSAN("unsigned-integer-overflow")
|
|
||||||
bool VerifyTableStart(const uint8_t* const table) {
|
|
||||||
// Check the vtable offset.
|
|
||||||
const auto tableo = static_cast<size_t>(table - buf_);
|
|
||||||
if (!Verify<soffset_t>(tableo)) return false;
|
|
||||||
// This offset may be signed, but doing the subtraction unsigned always
|
|
||||||
// gives the result we want.
|
|
||||||
const auto vtableo =
|
|
||||||
tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
|
|
||||||
// Check the vtable size field, then check vtable fits in its entirety.
|
|
||||||
if (!(VerifyComplexity() && Verify<voffset_t>(vtableo) &&
|
|
||||||
VerifyAlignment(ReadScalar<voffset_t>(buf_ + vtableo),
|
|
||||||
sizeof(voffset_t))))
|
|
||||||
return false;
|
|
||||||
const auto vsize = ReadScalar<voffset_t>(buf_ + vtableo);
|
|
||||||
return Check((vsize & 1) == 0) && Verify(vtableo, vsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool VerifyBufferFromStart(const char* const identifier, const size_t start) {
|
|
||||||
// Buffers have to be of some size to be valid. The reason it is a runtime
|
|
||||||
// check instead of static_assert, is that nested flatbuffers go through
|
|
||||||
// this call and their size is determined at runtime.
|
|
||||||
if (!Check(size_ >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
|
|
||||||
|
|
||||||
// If an identifier is provided, check that we have a buffer
|
|
||||||
if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) &&
|
|
||||||
BufferHasIdentifier(buf_ + start, identifier)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call T::Verify, which must be in the generated code for this type.
|
|
||||||
const auto o = VerifyOffset<uoffset_t>(start);
|
|
||||||
if (!Check(o != 0)) return false;
|
|
||||||
if (!(reinterpret_cast<const T*>(buf_ + start + o)->Verify(*this))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (TrackVerifierBufferSize) {
|
|
||||||
if (GetComputedSize() == 0) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, int&..., typename SizeT>
|
|
||||||
bool VerifyNestedFlatBuffer(const Vector<uint8_t, SizeT>* const buf,
|
|
||||||
const char* const identifier) {
|
|
||||||
// Caller opted out of this.
|
|
||||||
if (!opts_.check_nested_flatbuffers) return true;
|
|
||||||
|
|
||||||
// An empty buffer is OK as it indicates not present.
|
|
||||||
if (!buf) return true;
|
|
||||||
|
|
||||||
// If there is a nested buffer, it must be greater than the min size.
|
|
||||||
if (!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
|
|
||||||
|
|
||||||
VerifierTemplate<TrackVerifierBufferSize> nested_verifier(
|
|
||||||
buf->data(), buf->size(), opts_);
|
|
||||||
return nested_verifier.VerifyBuffer<T>(identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify this whole buffer, starting with root type T.
|
|
||||||
template <typename T>
|
|
||||||
bool VerifyBuffer() {
|
|
||||||
return VerifyBuffer<T>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool VerifyBuffer(const char* const identifier) {
|
|
||||||
return VerifyBufferFromStart<T>(identifier, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename SizeT = uoffset_t>
|
|
||||||
bool VerifySizePrefixedBuffer(const char* const identifier) {
|
|
||||||
return Verify<SizeT>(0U) &&
|
|
||||||
// Ensure the prefixed size is within the bounds of the provided
|
|
||||||
// length.
|
|
||||||
Check(ReadScalar<SizeT>(buf_) + sizeof(SizeT) <= size_) &&
|
|
||||||
VerifyBufferFromStart<T>(identifier, sizeof(SizeT));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OffsetT = uoffset_t, typename SOffsetT = soffset_t>
|
|
||||||
size_t VerifyOffset(const size_t start) const {
|
|
||||||
if (!Verify<OffsetT>(start)) return 0;
|
|
||||||
const auto o = ReadScalar<OffsetT>(buf_ + start);
|
|
||||||
// May not point to itself.
|
|
||||||
if (!Check(o != 0)) return 0;
|
|
||||||
// Can't wrap around larger than the max size.
|
|
||||||
if (!Check(static_cast<SOffsetT>(o) >= 0)) return 0;
|
|
||||||
// Must be inside the buffer to create a pointer from it (pointer outside
|
|
||||||
// buffer is UB).
|
|
||||||
if (!Verify(start + o, 1)) return 0;
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OffsetT = uoffset_t>
|
|
||||||
size_t VerifyOffset(const uint8_t* const base, const voffset_t start) const {
|
|
||||||
return VerifyOffset<OffsetT>(static_cast<size_t>(base - buf_) + start);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called at the start of a table to increase counters measuring data
|
|
||||||
// structure depth and amount, and possibly bails out with false if limits set
|
|
||||||
// by the constructor have been hit. Needs to be balanced with EndTable().
|
|
||||||
bool VerifyComplexity() {
|
|
||||||
depth_++;
|
|
||||||
num_tables_++;
|
|
||||||
return Check(depth_ <= opts_.max_depth && num_tables_ <= opts_.max_tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called at the end of a table to pop the depth count.
|
|
||||||
bool EndTable() {
|
|
||||||
depth_--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the message size in bytes.
|
|
||||||
//
|
|
||||||
// This should only be called after first calling VerifyBuffer or
|
|
||||||
// VerifySizePrefixedBuffer.
|
|
||||||
//
|
|
||||||
// This method should only be called for VerifierTemplate instances
|
|
||||||
// where the TrackVerifierBufferSize template parameter is true,
|
|
||||||
// i.e. for SizeVerifier. For instances where TrackVerifierBufferSize
|
|
||||||
// is false, this fails at runtime or returns zero.
|
|
||||||
size_t GetComputedSize() const {
|
|
||||||
if (TrackVerifierBufferSize) {
|
|
||||||
uintptr_t size = upper_bound_;
|
|
||||||
// Align the size to uoffset_t
|
|
||||||
size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
|
|
||||||
return (size > size_) ? 0 : size;
|
|
||||||
}
|
|
||||||
// Must use SizeVerifier, or (deprecated) turn on
|
|
||||||
// FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE, for this to work.
|
|
||||||
(void)upper_bound_;
|
|
||||||
FLATBUFFERS_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t>* GetFlexReuseTracker() { return flex_reuse_tracker_; }
|
|
||||||
|
|
||||||
void SetFlexReuseTracker(std::vector<uint8_t>* const rt) {
|
|
||||||
flex_reuse_tracker_ = rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const uint8_t* buf_;
|
|
||||||
const size_t size_;
|
|
||||||
const Options opts_;
|
|
||||||
|
|
||||||
mutable size_t upper_bound_ = 0;
|
|
||||||
|
|
||||||
uoffset_t depth_ = 0;
|
|
||||||
uoffset_t num_tables_ = 0;
|
|
||||||
std::vector<uint8_t>* flex_reuse_tracker_ = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialization for 64-bit offsets.
|
|
||||||
template <>
|
|
||||||
template <>
|
|
||||||
inline size_t VerifierTemplate<false>::VerifyOffset<uoffset64_t>(
|
|
||||||
const size_t start) const {
|
|
||||||
return VerifyOffset<uoffset64_t, soffset64_t>(start);
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
template <>
|
|
||||||
inline size_t VerifierTemplate<true>::VerifyOffset<uoffset64_t>(
|
|
||||||
const size_t start) const {
|
|
||||||
return VerifyOffset<uoffset64_t, soffset64_t>(start);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instance of VerifierTemplate that supports GetComputedSize().
|
|
||||||
using SizeVerifier = VerifierTemplate</*TrackVerifierBufferSize = */ true>;
|
|
||||||
|
|
||||||
// The FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE build configuration macro is
|
|
||||||
// deprecated, and should not be defined, since it is easy to misuse in ways
|
|
||||||
// that result in ODR violations. Rather than using Verifier and defining
|
|
||||||
// FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE, please use SizeVerifier instead.
|
|
||||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE // Deprecated, see above.
|
|
||||||
using Verifier = SizeVerifier;
|
|
||||||
#else
|
|
||||||
// Instance of VerifierTemplate that is slightly faster, but does not
|
|
||||||
// support GetComputedSize().
|
|
||||||
using Verifier = VerifierTemplate</*TrackVerifierBufferSize = */ false>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
|
|
||||||
#endif // FLATBUFFERS_VERIFIER_H_
|
|
||||||
-492
@@ -1,492 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
// Dont't remove `format off`, it prevent reordering of win-includes.
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#if defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__) || \
|
|
||||||
defined(__QNXNTO__)
|
|
||||||
# define _POSIX_C_SOURCE 200809L
|
|
||||||
# define _XOPEN_SOURCE 700L
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__)
|
|
||||||
# ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
# define WIN32_LEAN_AND_MEAN
|
|
||||||
# endif
|
|
||||||
# ifndef NOMINMAX
|
|
||||||
# define NOMINMAX
|
|
||||||
# endif
|
|
||||||
# ifdef _MSC_VER
|
|
||||||
# include <crtdbg.h>
|
|
||||||
# endif
|
|
||||||
# include <windows.h> // Must be included before <direct.h>
|
|
||||||
# ifndef __CYGWIN__
|
|
||||||
# include <direct.h>
|
|
||||||
# endif
|
|
||||||
# include <winbase.h>
|
|
||||||
# undef interface // This is also important because of reasons
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
#include "flatbuffers/util.h"
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <clocale>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <fstream>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
static bool FileExistsRaw(const char* name) {
|
|
||||||
std::ifstream ifs(name);
|
|
||||||
return ifs.good();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool LoadFileRaw(const char* name, bool binary, std::string* buf) {
|
|
||||||
if (DirExists(name)) return false;
|
|
||||||
std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in);
|
|
||||||
if (!ifs.is_open()) return false;
|
|
||||||
if (binary) {
|
|
||||||
// The fastest way to read a file into a string.
|
|
||||||
ifs.seekg(0, std::ios::end);
|
|
||||||
auto size = ifs.tellg();
|
|
||||||
(*buf).resize(static_cast<size_t>(size));
|
|
||||||
ifs.seekg(0, std::ios::beg);
|
|
||||||
ifs.read(&(*buf)[0], (*buf).size());
|
|
||||||
} else {
|
|
||||||
// This is slower, but works correctly on all platforms for text files.
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << ifs.rdbuf();
|
|
||||||
*buf = oss.str();
|
|
||||||
}
|
|
||||||
return !ifs.bad();
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadFileFunction g_load_file_function = LoadFileRaw;
|
|
||||||
FileExistsFunction g_file_exists_function = FileExistsRaw;
|
|
||||||
|
|
||||||
static std::string ToCamelCase(const std::string& input, bool is_upper) {
|
|
||||||
std::string s;
|
|
||||||
for (size_t i = 0; i < input.length(); i++) {
|
|
||||||
if (!i && input[i] == '_') {
|
|
||||||
s += input[i];
|
|
||||||
// we ignore leading underscore but make following
|
|
||||||
// alphabet char upper.
|
|
||||||
if (i + 1 < input.length() && is_alpha(input[i + 1]))
|
|
||||||
s += CharToUpper(input[++i]);
|
|
||||||
} else if (!i)
|
|
||||||
s += is_upper ? CharToUpper(input[i]) : CharToLower(input[i]);
|
|
||||||
else if (input[i] == '_' && i + 1 < input.length())
|
|
||||||
s += CharToUpper(input[++i]);
|
|
||||||
else
|
|
||||||
s += input[i];
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string ToSnakeCase(const std::string& input, bool screaming) {
|
|
||||||
std::string s;
|
|
||||||
for (size_t i = 0; i < input.length(); i++) {
|
|
||||||
if (i == 0) {
|
|
||||||
s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
|
|
||||||
} else if (input[i] == '_') {
|
|
||||||
s += '_';
|
|
||||||
} else if (!islower(input[i])) {
|
|
||||||
// Prevent duplicate underscores for Upper_Snake_Case strings
|
|
||||||
// and UPPERCASE strings.
|
|
||||||
if (islower(input[i - 1]) ||
|
|
||||||
(isdigit(input[i - 1]) && !isdigit(input[i]))) {
|
|
||||||
s += '_';
|
|
||||||
}
|
|
||||||
s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
|
|
||||||
} else {
|
|
||||||
s += screaming ? CharToUpper(input[i]) : input[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToAll(const std::string& input,
|
|
||||||
std::function<char(const char)> transform) {
|
|
||||||
std::string s;
|
|
||||||
for (size_t i = 0; i < input.length(); i++) {
|
|
||||||
s += transform(input[i]);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CamelToSnake(const std::string& input) {
|
|
||||||
std::string s;
|
|
||||||
for (size_t i = 0; i < input.length(); i++) {
|
|
||||||
if (i == 0) {
|
|
||||||
s += CharToLower(input[i]);
|
|
||||||
} else if (input[i] == '_') {
|
|
||||||
s += '_';
|
|
||||||
} else if (!islower(input[i])) {
|
|
||||||
// Prevent duplicate underscores for Upper_Snake_Case strings
|
|
||||||
// and UPPERCASE strings.
|
|
||||||
if (islower(input[i - 1]) ||
|
|
||||||
(isdigit(input[i - 1]) && !isdigit(input[i]))) {
|
|
||||||
s += '_';
|
|
||||||
}
|
|
||||||
s += CharToLower(input[i]);
|
|
||||||
} else {
|
|
||||||
s += input[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string DasherToSnake(const std::string& input) {
|
|
||||||
std::string s;
|
|
||||||
for (size_t i = 0; i < input.length(); i++) {
|
|
||||||
if (input[i] == '-') {
|
|
||||||
s += "_";
|
|
||||||
} else {
|
|
||||||
s += input[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToDasher(const std::string& input) {
|
|
||||||
std::string s;
|
|
||||||
char p = 0;
|
|
||||||
for (size_t i = 0; i < input.length(); i++) {
|
|
||||||
char const& c = input[i];
|
|
||||||
if (c == '_') {
|
|
||||||
if (i > 0 && p != kPathSeparator &&
|
|
||||||
// The following is a special case to ignore digits after a _. This is
|
|
||||||
// because ThisExample3 would be converted to this_example_3 in the
|
|
||||||
// CamelToSnake conversion, and then dasher would do this-example-3,
|
|
||||||
// but it expects this-example3.
|
|
||||||
!(i + 1 < input.length() && isdigit(input[i + 1])))
|
|
||||||
s += "-";
|
|
||||||
} else {
|
|
||||||
s += c;
|
|
||||||
}
|
|
||||||
p = c;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts foo_bar_123baz_456 to foo_bar123_baz456
|
|
||||||
std::string SnakeToSnake2(const std::string& s) {
|
|
||||||
if (s.length() <= 1) return s;
|
|
||||||
std::string result;
|
|
||||||
result.reserve(s.size());
|
|
||||||
for (size_t i = 0; i < s.length() - 1; i++) {
|
|
||||||
if (s[i] == '_' && isdigit(s[i + 1])) {
|
|
||||||
continue; // Move the `_` until after the digits.
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push_back(s[i]);
|
|
||||||
|
|
||||||
if (isdigit(s[i]) && isalpha(s[i + 1]) && islower(s[i + 1])) {
|
|
||||||
result.push_back('_');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.push_back(s.back());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
bool LoadFile(const char* name, bool binary, std::string* buf) {
|
|
||||||
FLATBUFFERS_ASSERT(g_load_file_function);
|
|
||||||
return g_load_file_function(name, binary, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileExists(const char* name) {
|
|
||||||
FLATBUFFERS_ASSERT(g_file_exists_function);
|
|
||||||
return g_file_exists_function(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DirExists(const char* name) {
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define flatbuffers_stat _stat
|
|
||||||
#define FLATBUFFERS_S_IFDIR _S_IFDIR
|
|
||||||
#else
|
|
||||||
#define flatbuffers_stat stat
|
|
||||||
#define FLATBUFFERS_S_IFDIR S_IFDIR
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
|
||||||
struct flatbuffers_stat file_info;
|
|
||||||
if (flatbuffers_stat(name, &file_info) != 0) return false;
|
|
||||||
return (file_info.st_mode & FLATBUFFERS_S_IFDIR) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function) {
|
|
||||||
LoadFileFunction previous_function = g_load_file_function;
|
|
||||||
g_load_file_function = load_file_function ? load_file_function : LoadFileRaw;
|
|
||||||
return previous_function;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileExistsFunction SetFileExistsFunction(
|
|
||||||
FileExistsFunction file_exists_function) {
|
|
||||||
FileExistsFunction previous_function = g_file_exists_function;
|
|
||||||
g_file_exists_function =
|
|
||||||
file_exists_function ? file_exists_function : FileExistsRaw;
|
|
||||||
return previous_function;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SaveFile(const char* name, const char* buf, size_t len, bool binary) {
|
|
||||||
std::ofstream ofs(name, binary ? std::ofstream::binary : std::ofstream::out);
|
|
||||||
if (!ofs.is_open()) return false;
|
|
||||||
ofs.write(buf, len);
|
|
||||||
return !ofs.bad();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We internally store paths in posix format ('/'). Paths supplied
|
|
||||||
// by the user should go through PosixPath to ensure correct behavior
|
|
||||||
// on Windows when paths are string-compared.
|
|
||||||
|
|
||||||
static const char kPathSeparatorWindows = '\\';
|
|
||||||
static const char* PathSeparatorSet = "\\/"; // Intentionally no ':'
|
|
||||||
|
|
||||||
std::string StripExtension(const std::string& filepath) {
|
|
||||||
size_t i = filepath.find_last_of('.');
|
|
||||||
return i != std::string::npos ? filepath.substr(0, i) : filepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetExtension(const std::string& filepath) {
|
|
||||||
size_t i = filepath.find_last_of('.');
|
|
||||||
return i != std::string::npos ? filepath.substr(i + 1) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string StripPath(const std::string& filepath) {
|
|
||||||
size_t i = filepath.find_last_of(PathSeparatorSet);
|
|
||||||
return i != std::string::npos ? filepath.substr(i + 1) : filepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string StripFileName(const std::string& filepath) {
|
|
||||||
size_t i = filepath.find_last_of(PathSeparatorSet);
|
|
||||||
return i != std::string::npos ? filepath.substr(0, i) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string StripPrefix(const std::string& filepath,
|
|
||||||
const std::string& prefix_to_remove) {
|
|
||||||
if (!strncmp(filepath.c_str(), prefix_to_remove.c_str(),
|
|
||||||
prefix_to_remove.size())) {
|
|
||||||
return filepath.substr(prefix_to_remove.size());
|
|
||||||
}
|
|
||||||
return filepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ConCatPathFileName(const std::string& path,
|
|
||||||
const std::string& filename) {
|
|
||||||
std::string filepath = path;
|
|
||||||
if (filepath.length()) {
|
|
||||||
char& filepath_last_character = filepath.back();
|
|
||||||
if (filepath_last_character == kPathSeparatorWindows) {
|
|
||||||
filepath_last_character = kPathSeparator;
|
|
||||||
} else if (filepath_last_character != kPathSeparator) {
|
|
||||||
filepath += kPathSeparator;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filepath += filename;
|
|
||||||
// Ignore './' at the start of filepath.
|
|
||||||
if (filepath[0] == '.' && filepath[1] == kPathSeparator) {
|
|
||||||
filepath.erase(0, 2);
|
|
||||||
}
|
|
||||||
return filepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PosixPath(const char* path) {
|
|
||||||
std::string p = path;
|
|
||||||
std::replace(p.begin(), p.end(), '\\', '/');
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
std::string PosixPath(const std::string& path) {
|
|
||||||
return PosixPath(path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnsureDirExists(const std::string& filepath) {
|
|
||||||
auto parent = StripFileName(filepath);
|
|
||||||
if (parent.length()) EnsureDirExists(parent);
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
(void)_mkdir(filepath.c_str());
|
|
||||||
#else
|
|
||||||
mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string FilePath(const std::string& project, const std::string& filePath,
|
|
||||||
bool absolute) {
|
|
||||||
return (absolute) ? AbsolutePath(filePath)
|
|
||||||
: RelativeToRootPath(project, filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AbsolutePath(const std::string& filepath) {
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
|
|
||||||
return filepath;
|
|
||||||
#else
|
|
||||||
#if defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__)
|
|
||||||
char abs_path[MAX_PATH];
|
|
||||||
return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
|
|
||||||
#else
|
|
||||||
char *abs_path_temp = realpath(filepath.c_str(), nullptr);
|
|
||||||
bool success = abs_path_temp != nullptr;
|
|
||||||
std::string abs_path;
|
|
||||||
if(success) {
|
|
||||||
abs_path = abs_path_temp;
|
|
||||||
free(abs_path_temp);
|
|
||||||
}
|
|
||||||
return success
|
|
||||||
#endif
|
|
||||||
? abs_path
|
|
||||||
: filepath;
|
|
||||||
#endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RelativeToRootPath(const std::string& project,
|
|
||||||
const std::string& filepath) {
|
|
||||||
std::string absolute_project = PosixPath(AbsolutePath(project));
|
|
||||||
if (absolute_project.back() != '/') absolute_project += "/";
|
|
||||||
std::string absolute_filepath = PosixPath(AbsolutePath(filepath));
|
|
||||||
|
|
||||||
// Find the first character where they disagree.
|
|
||||||
// The previous directory is the lowest common ancestor;
|
|
||||||
const char* a = absolute_project.c_str();
|
|
||||||
const char* b = absolute_filepath.c_str();
|
|
||||||
size_t common_prefix_len = 0;
|
|
||||||
while (*a != '\0' && *b != '\0' && *a == *b) {
|
|
||||||
if (*a == '/') common_prefix_len = a - absolute_project.c_str();
|
|
||||||
a++;
|
|
||||||
b++;
|
|
||||||
}
|
|
||||||
// the number of ../ to prepend to b depends on the number of remaining
|
|
||||||
// directories in A.
|
|
||||||
const char* suffix = absolute_project.c_str() + common_prefix_len;
|
|
||||||
size_t num_up = 0;
|
|
||||||
while (*suffix != '\0')
|
|
||||||
if (*suffix++ == '/') num_up++;
|
|
||||||
num_up--; // last one is known to be '/'.
|
|
||||||
std::string result = "//";
|
|
||||||
for (size_t i = 0; i < num_up; i++) result += "../";
|
|
||||||
result += absolute_filepath.substr(common_prefix_len + 1);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Locale-independent code.
|
|
||||||
#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && \
|
|
||||||
(FLATBUFFERS_LOCALE_INDEPENDENT > 0)
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
// Allocate locale instance at startup of application.
|
|
||||||
ClassicLocale ClassicLocale::instance_;
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
ClassicLocale::ClassicLocale()
|
|
||||||
: locale_(_create_locale(LC_ALL, "C")) {}
|
|
||||||
ClassicLocale::~ClassicLocale() { _free_locale(locale_); }
|
|
||||||
#else
|
|
||||||
ClassicLocale::ClassicLocale()
|
|
||||||
: locale_(newlocale(LC_ALL, "C", nullptr)) {}
|
|
||||||
ClassicLocale::~ClassicLocale() { freelocale(locale_); }
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
|
|
||||||
|
|
||||||
std::string RemoveStringQuotes(const std::string& s) {
|
|
||||||
auto ch = *s.c_str();
|
|
||||||
return ((s.size() >= 2) && (ch == '\"' || ch == '\'') && (ch == s.back()))
|
|
||||||
? s.substr(1, s.length() - 2)
|
|
||||||
: s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetGlobalTestLocale(const char* locale_name, std::string* _value) {
|
|
||||||
const auto the_locale = setlocale(LC_ALL, locale_name);
|
|
||||||
if (!the_locale) return false;
|
|
||||||
if (_value) *_value = std::string(the_locale);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReadEnvironmentVariable(const char* var_name, std::string* _value) {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
__pragma(warning(disable : 4996)); // _CRT_SECURE_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
auto env_str = std::getenv(var_name);
|
|
||||||
if (!env_str) return false;
|
|
||||||
if (_value) *_value = std::string(env_str);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ConvertCase(const std::string& input, Case output_case,
|
|
||||||
Case input_case) {
|
|
||||||
if (output_case == Case::kKeep) return input;
|
|
||||||
// The output cases expect snake_case inputs, so if we don't have that input
|
|
||||||
// format, try to convert to snake_case.
|
|
||||||
switch (input_case) {
|
|
||||||
case Case::kLowerCamel:
|
|
||||||
case Case::kUpperCamel:
|
|
||||||
return ConvertCase(CamelToSnake(input), output_case);
|
|
||||||
case Case::kDasher:
|
|
||||||
return ConvertCase(DasherToSnake(input), output_case);
|
|
||||||
case Case::kKeep:
|
|
||||||
printf("WARNING: Converting from kKeep case.\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case Case::kSnake:
|
|
||||||
case Case::kScreamingSnake:
|
|
||||||
case Case::kAllLower:
|
|
||||||
case Case::kAllUpper:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (output_case) {
|
|
||||||
case Case::kUpperCamel:
|
|
||||||
return ToCamelCase(input, true);
|
|
||||||
case Case::kLowerCamel:
|
|
||||||
return ToCamelCase(input, false);
|
|
||||||
case Case::kSnake:
|
|
||||||
return input;
|
|
||||||
case Case::kScreamingSnake:
|
|
||||||
return ToSnakeCase(input, true);
|
|
||||||
case Case::kAllUpper:
|
|
||||||
return ToAll(input, CharToUpper);
|
|
||||||
case Case::kAllLower:
|
|
||||||
return ToAll(input, CharToLower);
|
|
||||||
case Case::kDasher:
|
|
||||||
return ToDasher(input);
|
|
||||||
case Case::kSnake2:
|
|
||||||
return SnakeToSnake2(input);
|
|
||||||
default:
|
|
||||||
case Case::kUnknown:
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
|
||||||
-3423
File diff suppressed because it is too large
Load Diff
-343
@@ -1,343 +0,0 @@
|
|||||||
// https://github.com/CedricGuillemet/ImGuizmo
|
|
||||||
// v1.92.5 WIP
|
|
||||||
//
|
|
||||||
// The MIT License(MIT)
|
|
||||||
//
|
|
||||||
// Copyright(c) 2016-2026 Cedric Guillemet and contributors
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// -------------------------------------------------------------------------------------------
|
|
||||||
// History :
|
|
||||||
// 2026/05/03 v1.9 release. CMake build system, vcpkg support, many fixes and new features from contributors.
|
|
||||||
// 2019/11/03 View gizmo
|
|
||||||
// 2016/09/11 Behind camera culling. Scaling Delta matrix not multiplied by source matrix scales. local/world rotation and translation fixed. Display message is incorrect (X: ... Y:...) in local mode.
|
|
||||||
// 2016/09/09 Hatched negative axis. Snapping. Documentation update.
|
|
||||||
// 2016/09/04 Axis switch and translation plan autohiding. Scale transform stability improved
|
|
||||||
// 2016/09/01 Mogwai changed to Manipulate. Draw debug cube. Fixed inverted scale. Mixing scale and translation/rotation gives bad results.
|
|
||||||
// 2016/08/31 First version
|
|
||||||
//
|
|
||||||
// -------------------------------------------------------------------------------------------
|
|
||||||
// Future (no order):
|
|
||||||
//
|
|
||||||
// - Multi view
|
|
||||||
// - display rotation/translation/scale infos in local/world space and not only local
|
|
||||||
// - finish local/world matrix application
|
|
||||||
// - OPERATION as bitmask
|
|
||||||
//
|
|
||||||
// -------------------------------------------------------------------------------------------
|
|
||||||
// Example
|
|
||||||
#if 0
|
|
||||||
void EditTransform(const Camera& camera, matrix_t& matrix)
|
|
||||||
{
|
|
||||||
static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE);
|
|
||||||
static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD);
|
|
||||||
if (ImGui::IsKeyPressed(90))
|
|
||||||
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
|
|
||||||
if (ImGui::IsKeyPressed(69))
|
|
||||||
mCurrentGizmoOperation = ImGuizmo::ROTATE;
|
|
||||||
if (ImGui::IsKeyPressed(82)) // r Key
|
|
||||||
mCurrentGizmoOperation = ImGuizmo::SCALE;
|
|
||||||
if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
|
|
||||||
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE))
|
|
||||||
mCurrentGizmoOperation = ImGuizmo::ROTATE;
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE))
|
|
||||||
mCurrentGizmoOperation = ImGuizmo::SCALE;
|
|
||||||
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
|
|
||||||
ImGuizmo::DecomposeMatrixToComponents(matrix.m16, matrixTranslation, matrixRotation, matrixScale);
|
|
||||||
ImGui::InputFloat3("Tr", matrixTranslation, 3);
|
|
||||||
ImGui::InputFloat3("Rt", matrixRotation, 3);
|
|
||||||
ImGui::InputFloat3("Sc", matrixScale, 3);
|
|
||||||
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix.m16);
|
|
||||||
|
|
||||||
if (mCurrentGizmoOperation != ImGuizmo::SCALE)
|
|
||||||
{
|
|
||||||
if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
|
|
||||||
mCurrentGizmoMode = ImGuizmo::LOCAL;
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
|
|
||||||
mCurrentGizmoMode = ImGuizmo::WORLD;
|
|
||||||
}
|
|
||||||
static bool useSnap(false);
|
|
||||||
if (ImGui::IsKeyPressed(83))
|
|
||||||
useSnap = !useSnap;
|
|
||||||
ImGui::Checkbox("", &useSnap);
|
|
||||||
ImGui::SameLine();
|
|
||||||
vec_t snap;
|
|
||||||
switch (mCurrentGizmoOperation)
|
|
||||||
{
|
|
||||||
case ImGuizmo::TRANSLATE:
|
|
||||||
snap = config.mSnapTranslation;
|
|
||||||
ImGui::InputFloat3("Snap", &snap.x);
|
|
||||||
break;
|
|
||||||
case ImGuizmo::ROTATE:
|
|
||||||
snap = config.mSnapRotation;
|
|
||||||
ImGui::InputFloat("Angle Snap", &snap.x);
|
|
||||||
break;
|
|
||||||
case ImGuizmo::SCALE:
|
|
||||||
snap = config.mSnapScale;
|
|
||||||
ImGui::InputFloat("Scale Snap", &snap.x);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
|
|
||||||
ImGuizmo::Manipulate(camera.mView.m16, camera.mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, matrix.m16, NULL, useSnap ? &snap.x : NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef USE_IMGUI_API
|
|
||||||
#include "imconfig.h"
|
|
||||||
#endif
|
|
||||||
#ifndef IMGUI_API
|
|
||||||
#define IMGUI_API
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef IMGUIZMO_NAMESPACE
|
|
||||||
#define IMGUIZMO_NAMESPACE ImGuizmo
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ImGuiWindow;
|
|
||||||
|
|
||||||
namespace IMGUIZMO_NAMESPACE
|
|
||||||
{
|
|
||||||
// call inside your own window and before Manipulate() in order to draw gizmo to that window.
|
|
||||||
// Or pass a specific ImDrawList to draw to (e.g. ImGui::GetForegroundDrawList()).
|
|
||||||
IMGUI_API void SetDrawlist(ImDrawList* drawlist = nullptr);
|
|
||||||
|
|
||||||
// call BeginFrame right after ImGui_XXXX_NewFrame();
|
|
||||||
IMGUI_API void BeginFrame();
|
|
||||||
|
|
||||||
// this is necessary because when imguizmo is compiled into a dll, and imgui into another
|
|
||||||
// globals are not shared between them.
|
|
||||||
// More details at https://stackoverflow.com/questions/19373061/what-happens-to-global-and-static-variables-in-a-shared-library-when-it-is-dynam
|
|
||||||
// expose method to set imgui context
|
|
||||||
IMGUI_API void SetImGuiContext(ImGuiContext* ctx);
|
|
||||||
|
|
||||||
// return true if mouse cursor is over any gizmo control (axis, plan or screen component)
|
|
||||||
IMGUI_API bool IsOver();
|
|
||||||
|
|
||||||
// return true if mouse IsOver or if the gizmo is in moving state
|
|
||||||
IMGUI_API bool IsUsing();
|
|
||||||
|
|
||||||
// return true if the view gizmo is in moving state
|
|
||||||
IMGUI_API bool IsUsingViewManipulate();
|
|
||||||
// only check if your mouse is over the view manipulator - no matter whether it's active or not
|
|
||||||
IMGUI_API bool IsViewManipulateHovered();
|
|
||||||
|
|
||||||
// return true if any gizmo is in moving state
|
|
||||||
IMGUI_API bool IsUsingAny();
|
|
||||||
|
|
||||||
// enable/disable the gizmo. Stay in the state until next call to Enable.
|
|
||||||
// gizmo is rendered with gray half transparent color when disabled
|
|
||||||
IMGUI_API void Enable(bool enable);
|
|
||||||
|
|
||||||
// helper functions for manualy editing translation/rotation/scale with an input float
|
|
||||||
// translation, rotation and scale float points to 3 floats each
|
|
||||||
// Angles are in degrees (more suitable for human editing)
|
|
||||||
// example:
|
|
||||||
// float matrixTranslation[3], matrixRotation[3], matrixScale[3];
|
|
||||||
// ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale);
|
|
||||||
// ImGui::InputFloat3("Tr", matrixTranslation, 3);
|
|
||||||
// ImGui::InputFloat3("Rt", matrixRotation, 3);
|
|
||||||
// ImGui::InputFloat3("Sc", matrixScale, 3);
|
|
||||||
// ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);
|
|
||||||
//
|
|
||||||
// These functions have some numerical stability issues for now. Use with caution.
|
|
||||||
IMGUI_API void DecomposeMatrixToComponents(const float* matrix, float* translation, float* rotation, float* scale);
|
|
||||||
IMGUI_API void RecomposeMatrixFromComponents(const float* translation, const float* rotation, const float* scale, float* matrix);
|
|
||||||
|
|
||||||
IMGUI_API void SetRect(float x, float y, float width, float height);
|
|
||||||
// default is false
|
|
||||||
IMGUI_API void SetOrthographic(bool isOrthographic);
|
|
||||||
|
|
||||||
// Render coordinate system axes (red X, green Y and blue Z). Usefull for debug/tests
|
|
||||||
IMGUI_API void DrawAxes(const float* view, const float* projection, const float* matrices, int matrixCount);
|
|
||||||
// Render a cube with face color corresponding to face normal. Usefull for debug/tests
|
|
||||||
IMGUI_API void DrawCubes(const float* view, const float* projection, const float* matrices, int matrixCount);
|
|
||||||
IMGUI_API void DrawGrid(const float* view, const float* projection, const float* matrix, const float gridSize);
|
|
||||||
// Render grid with customizable major line step and amount of segments between major lines.
|
|
||||||
// NOTE(m.wlasiuk) : calling this function with majorStep = 1.0f and subdivision = 1 is equivalent to DrawGrid in terms of the end result but performs more calculations
|
|
||||||
IMGUI_API void DrawGridCustom(const float* view, const float* projection, const float* matrix, const float gridSize, const float majorStep, const unsigned int subdivision);
|
|
||||||
// Render grid with customizable major line step and amount of segments between major lines and with possibility to set custom colors for major, minor and center lines
|
|
||||||
IMGUI_API void DrawGridCustomColor(const float* view, const float* projection, const float* matrix, const float gridSize, const float majorStep, const unsigned int subdivision, const ImU32 majorCol, const ImU32 minorCol, const ImU32 centerCol);
|
|
||||||
|
|
||||||
// call it when you want a gizmo
|
|
||||||
// Needs view and projection matrices.
|
|
||||||
// matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional
|
|
||||||
// translation is applied in world space
|
|
||||||
enum OPERATION
|
|
||||||
{
|
|
||||||
TRANSLATE_X = (1u << 0),
|
|
||||||
TRANSLATE_Y = (1u << 1),
|
|
||||||
TRANSLATE_Z = (1u << 2),
|
|
||||||
ROTATE_X = (1u << 3),
|
|
||||||
ROTATE_Y = (1u << 4),
|
|
||||||
ROTATE_Z = (1u << 5),
|
|
||||||
ROTATE_SCREEN = (1u << 6),
|
|
||||||
SCALE_X = (1u << 7),
|
|
||||||
SCALE_Y = (1u << 8),
|
|
||||||
SCALE_Z = (1u << 9),
|
|
||||||
BOUNDS = (1u << 10),
|
|
||||||
SCALE_XU = (1u << 11),
|
|
||||||
SCALE_YU = (1u << 12),
|
|
||||||
SCALE_ZU = (1u << 13),
|
|
||||||
|
|
||||||
TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z,
|
|
||||||
ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN,
|
|
||||||
SCALE = SCALE_X | SCALE_Y | SCALE_Z,
|
|
||||||
SCALEU = SCALE_XU | SCALE_YU | SCALE_ZU, // universal
|
|
||||||
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
|
|
||||||
};
|
|
||||||
|
|
||||||
inline OPERATION operator|(OPERATION lhs, OPERATION rhs)
|
|
||||||
{
|
|
||||||
return static_cast<OPERATION>(static_cast<int>(lhs) | static_cast<int>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MODE
|
|
||||||
{
|
|
||||||
LOCAL,
|
|
||||||
WORLD
|
|
||||||
};
|
|
||||||
|
|
||||||
IMGUI_API bool Manipulate(const float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float* deltaMatrix = NULL, const float* snap = NULL, const float* localBounds = NULL, const float* boundsSnap = NULL);
|
|
||||||
//
|
|
||||||
// Please note that this cubeview is patented by Autodesk : https://patents.google.com/patent/US7782319B2/en
|
|
||||||
// It seems to be a defensive patent in the US. I don't think it will bring troubles using it as
|
|
||||||
// other software are using the same mechanics. But just in case, you are now warned!
|
|
||||||
//
|
|
||||||
IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);
|
|
||||||
|
|
||||||
// use this version if you did not call Manipulate before and you are just using ViewManipulate
|
|
||||||
IMGUI_API void ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);
|
|
||||||
|
|
||||||
IMGUI_API void SetAlternativeWindow(ImGuiWindow* window);
|
|
||||||
|
|
||||||
[[deprecated("Use PushID/PopID instead.")]]
|
|
||||||
IMGUI_API void SetID(int id);
|
|
||||||
|
|
||||||
// ID stack/scopes
|
|
||||||
// Read the FAQ (docs/FAQ.md or http://dearimgui.org/faq) for more details about how ID are handled in dear imgui.
|
|
||||||
// - Those questions are answered and impacted by understanding of the ID stack system:
|
|
||||||
// - "Q: Why is my widget not reacting when I click on it?"
|
|
||||||
// - "Q: How can I have widgets with an empty label?"
|
|
||||||
// - "Q: How can I have multiple widgets with the same label?"
|
|
||||||
// - Short version: ID are hashes of the entire ID stack. If you are creating widgets in a loop you most likely
|
|
||||||
// want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them.
|
|
||||||
// - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others.
|
|
||||||
// - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID,
|
|
||||||
// whereas "str_id" denote a string that is only used as an ID and not normally displayed.
|
|
||||||
IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string).
|
|
||||||
IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string).
|
|
||||||
IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack (will hash pointer).
|
|
||||||
IMGUI_API void PushID(int int_id); // push integer into the ID stack (will hash integer).
|
|
||||||
IMGUI_API void PopID(); // pop from the ID stack.
|
|
||||||
IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself
|
|
||||||
IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end);
|
|
||||||
IMGUI_API ImGuiID GetID(const void* ptr_id);
|
|
||||||
|
|
||||||
// return true if the cursor is over the operation's gizmo
|
|
||||||
IMGUI_API bool IsOver(OPERATION op);
|
|
||||||
IMGUI_API void SetGizmoSizeClipSpace(float value);
|
|
||||||
|
|
||||||
// Handle type used by the translate/rotate/scale gizmos.
|
|
||||||
enum MOVETYPE
|
|
||||||
{
|
|
||||||
MT_NONE,
|
|
||||||
MT_MOVE_X,
|
|
||||||
MT_MOVE_Y,
|
|
||||||
MT_MOVE_Z,
|
|
||||||
MT_MOVE_YZ,
|
|
||||||
MT_MOVE_ZX,
|
|
||||||
MT_MOVE_XY,
|
|
||||||
MT_MOVE_SCREEN,
|
|
||||||
MT_ROTATE_X,
|
|
||||||
MT_ROTATE_Y,
|
|
||||||
MT_ROTATE_Z,
|
|
||||||
MT_ROTATE_SCREEN,
|
|
||||||
MT_SCALE_X,
|
|
||||||
MT_SCALE_Y,
|
|
||||||
MT_SCALE_Z,
|
|
||||||
MT_SCALE_XYZ
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns which handle is actively being dragged, or MT_NONE.
|
|
||||||
IMGUI_API MOVETYPE GetActiveHandleType();
|
|
||||||
// Returns which handle is currently hovered, or MT_NONE.
|
|
||||||
IMGUI_API MOVETYPE GetHoveredHandleType();
|
|
||||||
// Aliases matching the MOVETYPE enum name.
|
|
||||||
IMGUI_API MOVETYPE GetActiveMoveType();
|
|
||||||
IMGUI_API MOVETYPE GetHoveredMoveType();
|
|
||||||
|
|
||||||
// Allow axis to flip
|
|
||||||
// When true (default), the guizmo axis flip for better visibility
|
|
||||||
// When false, they always stay along the positive world/local axis
|
|
||||||
IMGUI_API void AllowAxisFlip(bool value);
|
|
||||||
|
|
||||||
// Configure the limit where axis are hidden
|
|
||||||
IMGUI_API void SetAxisLimit(float value);
|
|
||||||
// Set an axis mask to permanently hide a given axis (true -> hidden, false -> shown)
|
|
||||||
IMGUI_API void SetAxisMask(bool x, bool y, bool z);
|
|
||||||
// Configure the limit where planes are hiden
|
|
||||||
IMGUI_API void SetPlaneLimit(float value);
|
|
||||||
// from a x,y,z point in space and using Manipulation view/projection matrix, check if mouse is in pixel radius distance of that projected point
|
|
||||||
IMGUI_API bool IsOver(float* position, float pixelRadius);
|
|
||||||
|
|
||||||
enum COLOR
|
|
||||||
{
|
|
||||||
DIRECTION_X, // directionColor[0]
|
|
||||||
DIRECTION_Y, // directionColor[1]
|
|
||||||
DIRECTION_Z, // directionColor[2]
|
|
||||||
PLANE_X, // planeColor[0]
|
|
||||||
PLANE_Y, // planeColor[1]
|
|
||||||
PLANE_Z, // planeColor[2]
|
|
||||||
SELECTION, // selectionColor
|
|
||||||
INACTIVE, // inactiveColor
|
|
||||||
TRANSLATION_LINE, // translationLineColor
|
|
||||||
SCALE_LINE,
|
|
||||||
ROTATION_USING_BORDER,
|
|
||||||
ROTATION_USING_FILL,
|
|
||||||
HATCHED_AXIS_LINES,
|
|
||||||
TEXT,
|
|
||||||
TEXT_SHADOW,
|
|
||||||
COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Style
|
|
||||||
{
|
|
||||||
IMGUI_API Style();
|
|
||||||
|
|
||||||
float TranslationLineThickness; // Thickness of lines for translation gizmo
|
|
||||||
float TranslationLineArrowSize; // Size of arrow at the end of lines for translation gizmo
|
|
||||||
float RotationLineThickness; // Thickness of lines for rotation gizmo
|
|
||||||
float RotationOuterLineThickness; // Thickness of line surrounding the rotation gizmo
|
|
||||||
float ScaleLineThickness; // Thickness of lines for scale gizmo
|
|
||||||
float ScaleLineCircleSize; // Size of circle at the end of lines for scale gizmo
|
|
||||||
float HatchedAxisLineThickness; // Thickness of hatched axis lines
|
|
||||||
float CenterCircleSize; // Size of circle at the center of the translate/scale gizmo
|
|
||||||
|
|
||||||
ImVec4 Colors[COLOR::COUNT];
|
|
||||||
};
|
|
||||||
|
|
||||||
IMGUI_API Style& GetStyle();
|
|
||||||
}
|
|
||||||
-21
@@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016 Cedric Guillemet
|
|
||||||
|
|
||||||
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.
|
|
||||||
-149
@@ -1,149 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// DEAR IMGUI COMPILE-TIME OPTIONS
|
|
||||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
|
||||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
|
||||||
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
|
||||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
|
||||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
|
||||||
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
//---- Define assertion handler. Defaults to calling assert().
|
|
||||||
// - If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
|
||||||
// - Compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes.
|
|
||||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
|
||||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
|
||||||
|
|
||||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
|
||||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
|
||||||
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
|
||||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
|
||||||
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
|
|
||||||
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
|
|
||||||
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
|
|
||||||
|
|
||||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
|
||||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
|
||||||
|
|
||||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
|
||||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
|
||||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
|
||||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
|
||||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
|
|
||||||
|
|
||||||
//---- Don't implement some functions to reduce linkage requirements.
|
|
||||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
|
||||||
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
|
||||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
|
||||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
|
||||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
|
||||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean + ProggyForever). Remove ~9 KB + ~14 KB from output binary. AddFontDefaultXXX() functions will assert.
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FONT_BITMAP // Disable default embedded bitmap font (ProggyClean). Remove ~9 KB from output binary. AddFontDefaultBitmap() will assert.
|
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FONT_VECTOR // Disable default embedded vector font (ProggyForever), Remove ~14 KB from output binary. AddFontDefaultVector() will assert.
|
|
||||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
|
||||||
|
|
||||||
//---- Enable Test Engine / Automation features.
|
|
||||||
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
|
|
||||||
|
|
||||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
|
||||||
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
|
||||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
|
||||||
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
|
|
||||||
|
|
||||||
//---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support.
|
|
||||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
|
||||||
|
|
||||||
//---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate.
|
|
||||||
//#define IMGUI_USE_LEGACY_CRC32_ADLER
|
|
||||||
|
|
||||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
|
||||||
//#define IMGUI_USE_WCHAR32
|
|
||||||
|
|
||||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
|
||||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
|
||||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
|
||||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
|
||||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
|
||||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
|
||||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
|
||||||
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
|
||||||
|
|
||||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
|
||||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
|
||||||
//#define IMGUI_USE_STB_SPRINTF
|
|
||||||
|
|
||||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
|
||||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
|
||||||
// Note that imgui_freetype.cpp may be used _without_ this define, if you manually call ImFontAtlas::SetFontLoader(). The define is simply a convenience.
|
|
||||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
|
||||||
//#define IMGUI_ENABLE_FREETYPE
|
|
||||||
|
|
||||||
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
|
|
||||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
|
||||||
// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions.
|
|
||||||
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
|
|
||||||
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
|
||||||
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
|
|
||||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
|
||||||
|
|
||||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
|
||||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
|
||||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
|
||||||
|
|
||||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
|
||||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
|
||||||
/*
|
|
||||||
#define IM_VEC2_CLASS_EXTRA \
|
|
||||||
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
|
||||||
operator MyVec2() const { return MyVec2(x,y); }
|
|
||||||
|
|
||||||
#define IM_VEC4_CLASS_EXTRA \
|
|
||||||
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
|
||||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
|
||||||
*/
|
|
||||||
//---- ...Or use Dear ImGui's own very basic math operators.
|
|
||||||
//#define IMGUI_DEFINE_MATH_OPERATORS
|
|
||||||
|
|
||||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
|
||||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
|
||||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
|
||||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
|
||||||
//#define ImDrawIdx unsigned int
|
|
||||||
|
|
||||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
|
||||||
//struct ImDrawList;
|
|
||||||
//struct ImDrawCmd;
|
|
||||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
|
||||||
//#define ImDrawCallback MyImDrawCallback
|
|
||||||
|
|
||||||
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
|
||||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
|
||||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
|
||||||
//#define IM_DEBUG_BREAK __debugbreak()
|
|
||||||
|
|
||||||
//---- Debug Tools: Enable highlight ID conflicts _before_ hovering items. When io.ConfigDebugHighlightIdConflicts is set.
|
|
||||||
// (THIS WILL SLOW DOWN DEAR IMGUI. Only use occasionally and disable after use)
|
|
||||||
//#define IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS
|
|
||||||
|
|
||||||
//---- Debug Tools: Enable slower asserts
|
|
||||||
//#define IMGUI_DEBUG_PARANOID
|
|
||||||
|
|
||||||
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
|
||||||
/*
|
|
||||||
namespace ImGui
|
|
||||||
{
|
|
||||||
void MyFunction(const char* name, MyMatrix44* mtx);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
-18385
File diff suppressed because it is too large
Load Diff
Vendored
-4256
File diff suppressed because it is too large
Load Diff
-6809
File diff suppressed because it is too large
Load Diff
-491
@@ -1,491 +0,0 @@
|
|||||||
// dear imgui: Renderer Backend for DirectX9
|
|
||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
|
||||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
|
||||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
|
||||||
// [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
|
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
|
||||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
|
||||||
// Learn about Dear ImGui:
|
|
||||||
// - FAQ https://dearimgui.com/faq
|
|
||||||
// - Getting Started https://dearimgui.com/getting-started
|
|
||||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
|
||||||
// - Introduction, links and more at the top of imgui.cpp
|
|
||||||
|
|
||||||
// CHANGELOG
|
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
|
||||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
|
||||||
// 2026-03-19: Fixed issue in ImGui_ImplDX9_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
|
||||||
// 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
|
||||||
// 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
|
||||||
// 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575)
|
|
||||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
|
||||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
|
||||||
// 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1.
|
|
||||||
// 2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
|
||||||
// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
|
|
||||||
// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
|
|
||||||
// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
|
|
||||||
// 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer.
|
|
||||||
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
|
||||||
// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
|
||||||
// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
|
|
||||||
// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
|
|
||||||
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
|
|
||||||
// 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
|
|
||||||
// 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
|
||||||
// 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud.
|
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
|
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#ifndef IMGUI_DISABLE
|
|
||||||
#include "imgui_impl_dx9.h"
|
|
||||||
|
|
||||||
// DirectX
|
|
||||||
#include <d3d9.h>
|
|
||||||
|
|
||||||
// Clang/GCC warnings with -Weverything
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
|
|
||||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// DirectX data
|
|
||||||
struct ImGui_ImplDX9_Data
|
|
||||||
{
|
|
||||||
LPDIRECT3DDEVICE9 pd3dDevice;
|
|
||||||
LPDIRECT3DVERTEXBUFFER9 pVB;
|
|
||||||
LPDIRECT3DINDEXBUFFER9 pIB;
|
|
||||||
int VertexBufferSize;
|
|
||||||
int IndexBufferSize;
|
|
||||||
bool HasRgbaSupport;
|
|
||||||
|
|
||||||
ImGui_ImplDX9_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CUSTOMVERTEX
|
|
||||||
{
|
|
||||||
float pos[3];
|
|
||||||
D3DCOLOR col;
|
|
||||||
float uv[2];
|
|
||||||
};
|
|
||||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
|
||||||
|
|
||||||
#ifdef IMGUI_USE_BGRA_PACKED_COLOR
|
|
||||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (_COL)
|
|
||||||
#else
|
|
||||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
|
||||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
|
||||||
static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData()
|
|
||||||
{
|
|
||||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
|
||||||
{
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
|
||||||
|
|
||||||
// Setup viewport
|
|
||||||
D3DVIEWPORT9 vp;
|
|
||||||
vp.X = vp.Y = 0;
|
|
||||||
vp.Width = (DWORD)draw_data->DisplaySize.x;
|
|
||||||
vp.Height = (DWORD)draw_data->DisplaySize.y;
|
|
||||||
vp.MinZ = 0.0f;
|
|
||||||
vp.MaxZ = 1.0f;
|
|
||||||
|
|
||||||
LPDIRECT3DDEVICE9 device = bd->pd3dDevice;
|
|
||||||
device->SetViewport(&vp);
|
|
||||||
|
|
||||||
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient), bilinear sampling.
|
|
||||||
device->SetPixelShader(nullptr);
|
|
||||||
device->SetVertexShader(nullptr);
|
|
||||||
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
|
||||||
device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
|
||||||
device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
|
||||||
device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
|
||||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
|
||||||
device->SetRenderState(D3DRS_ZENABLE, FALSE);
|
|
||||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
|
||||||
device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
|
||||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
|
||||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
|
||||||
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
|
||||||
device->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
|
|
||||||
device->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
|
|
||||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
|
||||||
device->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
|
||||||
device->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
|
|
||||||
device->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
|
|
||||||
device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
|
||||||
device->SetRenderState(D3DRS_CLIPPING, TRUE);
|
|
||||||
device->SetRenderState(D3DRS_LIGHTING, FALSE);
|
|
||||||
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
||||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|
||||||
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
|
||||||
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
|
||||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
|
||||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
|
||||||
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
||||||
device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
|
||||||
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
|
||||||
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
|
||||||
device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
|
||||||
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
|
||||||
|
|
||||||
// Setup orthographic projection matrix
|
|
||||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
|
||||||
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
|
|
||||||
{
|
|
||||||
float L = draw_data->DisplayPos.x + 0.5f;
|
|
||||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
|
|
||||||
float T = draw_data->DisplayPos.y + 0.5f;
|
|
||||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
|
|
||||||
D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
|
|
||||||
D3DMATRIX mat_projection =
|
|
||||||
{ { {
|
|
||||||
2.0f/(R-L), 0.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 2.0f/(T-B), 0.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 0.5f, 0.0f,
|
|
||||||
(L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
|
|
||||||
} } };
|
|
||||||
device->SetTransform(D3DTS_WORLD, &mat_identity);
|
|
||||||
device->SetTransform(D3DTS_VIEW, &mat_identity);
|
|
||||||
device->SetTransform(D3DTS_PROJECTION, &mat_projection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw callbacks
|
|
||||||
static void ImGui_ImplDX9_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
|
||||||
static void ImGui_ImplDX9_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); }
|
|
||||||
static void ImGui_ImplDX9_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); }
|
|
||||||
|
|
||||||
// Render function.
|
|
||||||
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
|
||||||
{
|
|
||||||
// Avoid rendering when minimized
|
|
||||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
|
||||||
LPDIRECT3DDEVICE9 device = bd->pd3dDevice;
|
|
||||||
|
|
||||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
|
||||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
|
||||||
if (draw_data->Textures != nullptr)
|
|
||||||
for (ImTextureData* tex : *draw_data->Textures)
|
|
||||||
if (tex->Status != ImTextureStatus_OK)
|
|
||||||
ImGui_ImplDX9_UpdateTexture(tex);
|
|
||||||
|
|
||||||
// Create and grow buffers if needed
|
|
||||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
|
||||||
{
|
|
||||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
|
||||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
|
||||||
if (device->CreateVertexBuffer((UINT)bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
|
||||||
{
|
|
||||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
|
||||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
|
||||||
if (device->CreateIndexBuffer((UINT)bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backup the DX9 state
|
|
||||||
IDirect3DStateBlock9* state_block = nullptr;
|
|
||||||
if (device->CreateStateBlock(D3DSBT_ALL, &state_block) < 0)
|
|
||||||
return;
|
|
||||||
if (state_block->Capture() < 0)
|
|
||||||
{
|
|
||||||
state_block->Release();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
|
|
||||||
D3DMATRIX last_world, last_view, last_projection;
|
|
||||||
device->GetTransform(D3DTS_WORLD, &last_world);
|
|
||||||
device->GetTransform(D3DTS_VIEW, &last_view);
|
|
||||||
device->GetTransform(D3DTS_PROJECTION, &last_projection);
|
|
||||||
|
|
||||||
// Allocate buffers
|
|
||||||
CUSTOMVERTEX* vtx_dst;
|
|
||||||
ImDrawIdx* idx_dst;
|
|
||||||
if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
|
||||||
{
|
|
||||||
state_block->Release();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
|
||||||
{
|
|
||||||
bd->pVB->Unlock();
|
|
||||||
state_block->Release();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
|
|
||||||
// FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
|
|
||||||
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
|
|
||||||
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
|
||||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
|
||||||
{
|
|
||||||
const ImDrawVert* vtx_src = draw_list->VtxBuffer.Data;
|
|
||||||
for (int i = 0; i < draw_list->VtxBuffer.Size; i++)
|
|
||||||
{
|
|
||||||
vtx_dst->pos[0] = vtx_src->pos.x;
|
|
||||||
vtx_dst->pos[1] = vtx_src->pos.y;
|
|
||||||
vtx_dst->pos[2] = 0.0f;
|
|
||||||
vtx_dst->col = IMGUI_COL_TO_DX9_ARGB(vtx_src->col);
|
|
||||||
vtx_dst->uv[0] = vtx_src->uv.x;
|
|
||||||
vtx_dst->uv[1] = vtx_src->uv.y;
|
|
||||||
vtx_dst++;
|
|
||||||
vtx_src++;
|
|
||||||
}
|
|
||||||
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
|
||||||
idx_dst += draw_list->IdxBuffer.Size;
|
|
||||||
}
|
|
||||||
bd->pVB->Unlock();
|
|
||||||
bd->pIB->Unlock();
|
|
||||||
device->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX));
|
|
||||||
device->SetIndices(bd->pIB);
|
|
||||||
device->SetFVF(D3DFVF_CUSTOMVERTEX);
|
|
||||||
|
|
||||||
// Setup desired DX state
|
|
||||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
|
||||||
|
|
||||||
// Render command lists
|
|
||||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
|
||||||
int global_vtx_offset = 0;
|
|
||||||
int global_idx_offset = 0;
|
|
||||||
ImVec2 clip_off = draw_data->DisplayPos;
|
|
||||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
|
||||||
{
|
|
||||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
|
||||||
{
|
|
||||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
|
||||||
if (pcmd->UserCallback != nullptr)
|
|
||||||
{
|
|
||||||
// User callback, registered via ImDrawList::AddCallback()
|
|
||||||
if (pcmd->UserCallback == ImGui_ImplDX9_DrawCallback_ResetRenderState)
|
|
||||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
|
||||||
else
|
|
||||||
pcmd->UserCallback(draw_list, pcmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Project scissor/clipping rectangles into framebuffer space
|
|
||||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
|
||||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
|
||||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Apply scissor/clipping rectangle
|
|
||||||
const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
|
||||||
device->SetScissorRect(&r);
|
|
||||||
|
|
||||||
// Bind texture, Draw
|
|
||||||
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
|
|
||||||
device->SetTexture(0, texture);
|
|
||||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)draw_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
global_idx_offset += draw_list->IdxBuffer.Size;
|
|
||||||
global_vtx_offset += draw_list->VtxBuffer.Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the DX9 transform
|
|
||||||
device->SetTransform(D3DTS_WORLD, &last_world);
|
|
||||||
device->SetTransform(D3DTS_VIEW, &last_view);
|
|
||||||
device->SetTransform(D3DTS_PROJECTION, &last_projection);
|
|
||||||
|
|
||||||
// Restore the DX9 state
|
|
||||||
state_block->Apply();
|
|
||||||
state_block->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ImGui_ImplDX9_CheckFormatSupport(LPDIRECT3DDEVICE9 pDevice, D3DFORMAT format)
|
|
||||||
{
|
|
||||||
LPDIRECT3D9 pd3d = nullptr;
|
|
||||||
if (pDevice->GetDirect3D(&pd3d) != D3D_OK)
|
|
||||||
return false;
|
|
||||||
D3DDEVICE_CREATION_PARAMETERS param = {};
|
|
||||||
D3DDISPLAYMODE mode = {};
|
|
||||||
if (pDevice->GetCreationParameters(¶m) != D3D_OK || pDevice->GetDisplayMode(0, &mode) != D3D_OK)
|
|
||||||
{
|
|
||||||
pd3d->Release();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Font texture should support linear filter, color blend and write to render-target
|
|
||||||
bool support = (pd3d->CheckDeviceFormat(param.AdapterOrdinal, param.DeviceType, mode.Format, D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, format)) == D3D_OK;
|
|
||||||
pd3d->Release();
|
|
||||||
return support;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
|
||||||
static void ImGui_ImplDX9_CopyTextureRegion(bool tex_use_colors, const ImU32* src, int src_pitch, ImU32* dst, int dst_pitch, int w, int h)
|
|
||||||
{
|
|
||||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
|
||||||
const bool convert_rgba_to_bgra = (!bd->HasRgbaSupport && tex_use_colors);
|
|
||||||
#else
|
|
||||||
const bool convert_rgba_to_bgra = false;
|
|
||||||
IM_UNUSED(tex_use_colors);
|
|
||||||
#endif
|
|
||||||
for (int y = 0; y < h; y++)
|
|
||||||
{
|
|
||||||
const ImU32* src_p = (const ImU32*)(const void*)((const unsigned char*)src + src_pitch * y);
|
|
||||||
ImU32* dst_p = (ImU32*)(void*)((unsigned char*)dst + dst_pitch * y);
|
|
||||||
if (convert_rgba_to_bgra)
|
|
||||||
for (int x = w; x > 0; x--, src_p++, dst_p++) // Convert copy
|
|
||||||
*dst_p = IMGUI_COL_TO_DX9_ARGB(*src_p);
|
|
||||||
else
|
|
||||||
memcpy(dst_p, src_p, w * 4); // Raw copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
|
|
||||||
{
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
|
||||||
|
|
||||||
if (tex->Status == ImTextureStatus_WantCreate)
|
|
||||||
{
|
|
||||||
// Create and upload new texture to graphics system
|
|
||||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
|
||||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
|
||||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
|
||||||
LPDIRECT3DTEXTURE9 dx_tex = nullptr;
|
|
||||||
HRESULT hr = bd->pd3dDevice->CreateTexture(tex->Width, tex->Height, 1, D3DUSAGE_DYNAMIC, bd->HasRgbaSupport ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dx_tex, nullptr);
|
|
||||||
if (hr < 0)
|
|
||||||
{
|
|
||||||
IM_ASSERT(hr >= 0 && "Backend failed to create texture!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3DLOCKED_RECT locked_rect;
|
|
||||||
if (dx_tex->LockRect(0, &locked_rect, nullptr, 0) == D3D_OK)
|
|
||||||
{
|
|
||||||
ImGui_ImplDX9_CopyTextureRegion(tex->UseColors, (ImU32*)tex->GetPixels(), tex->Width * 4, (ImU32*)locked_rect.pBits, (ImU32)locked_rect.Pitch, tex->Width, tex->Height);
|
|
||||||
dx_tex->UnlockRect(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store identifiers
|
|
||||||
tex->SetTexID((ImTextureID)(intptr_t)dx_tex);
|
|
||||||
tex->SetStatus(ImTextureStatus_OK);
|
|
||||||
}
|
|
||||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
|
||||||
{
|
|
||||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
|
||||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
|
||||||
LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)(intptr_t)tex->TexID;
|
|
||||||
RECT update_rect = { (LONG)tex->UpdateRect.x, (LONG)tex->UpdateRect.y, (LONG)(tex->UpdateRect.x + tex->UpdateRect.w), (LONG)(tex->UpdateRect.y + tex->UpdateRect.h) };
|
|
||||||
D3DLOCKED_RECT locked_rect;
|
|
||||||
if (backend_tex->LockRect(0, &locked_rect, &update_rect, 0) == D3D_OK)
|
|
||||||
for (ImTextureRect& r : tex->Updates)
|
|
||||||
ImGui_ImplDX9_CopyTextureRegion(tex->UseColors, (ImU32*)tex->GetPixelsAt(r.x, r.y), tex->Width * 4,
|
|
||||||
(ImU32*)locked_rect.pBits + (r.x - update_rect.left) + (r.y - update_rect.top) * (locked_rect.Pitch / 4), (int)locked_rect.Pitch, r.w, r.h);
|
|
||||||
backend_tex->UnlockRect(0);
|
|
||||||
tex->SetStatus(ImTextureStatus_OK);
|
|
||||||
}
|
|
||||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
|
||||||
{
|
|
||||||
if (tex->TexID != ImTextureID_Invalid)
|
|
||||||
if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
|
|
||||||
{
|
|
||||||
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
|
|
||||||
backend_tex->Release();
|
|
||||||
|
|
||||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
|
||||||
tex->SetTexID(ImTextureID_Invalid);
|
|
||||||
}
|
|
||||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplDX9_CreateDeviceObjects()
|
|
||||||
{
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
|
||||||
if (!bd || !bd->pd3dDevice)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplDX9_InvalidateDeviceObjects()
|
|
||||||
{
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
|
||||||
if (!bd || !bd->pd3dDevice)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Destroy all textures
|
|
||||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
|
||||||
if (tex->RefCount == 1)
|
|
||||||
{
|
|
||||||
tex->SetStatus(ImTextureStatus_WantDestroy);
|
|
||||||
ImGui_ImplDX9_UpdateTexture(tex);
|
|
||||||
}
|
|
||||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
|
||||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplDX9_NewFrame()
|
|
||||||
{
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
|
||||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX9_Init()?");
|
|
||||||
IM_UNUSED(bd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
IMGUI_CHECKVERSION();
|
|
||||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
|
||||||
ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
|
|
||||||
io.BackendRendererUserData = (void*)bd;
|
|
||||||
io.BackendRendererName = "imgui_impl_dx9";
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
|
||||||
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
|
||||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = 4096;
|
|
||||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX9_DrawCallback_ResetRenderState;
|
|
||||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX9_DrawCallback_SetSamplerLinear;
|
|
||||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX9_DrawCallback_SetSamplerNearest;
|
|
||||||
|
|
||||||
bd->pd3dDevice = device;
|
|
||||||
bd->pd3dDevice->AddRef();
|
|
||||||
bd->HasRgbaSupport = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplDX9_Shutdown()
|
|
||||||
{
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
|
||||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
|
||||||
|
|
||||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
|
||||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
|
||||||
|
|
||||||
io.BackendRendererName = nullptr;
|
|
||||||
io.BackendRendererUserData = nullptr;
|
|
||||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
|
||||||
platform_io.ClearRendererHandlers();
|
|
||||||
IM_DELETE(bd);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#endif // #ifndef IMGUI_DISABLE
|
|
||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
// dear imgui: Renderer Backend for DirectX9
|
|
||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
|
||||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
|
||||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
|
||||||
// [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
|
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
|
||||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
|
||||||
// Learn about Dear ImGui:
|
|
||||||
// - FAQ https://dearimgui.com/faq
|
|
||||||
// - Getting Started https://dearimgui.com/getting-started
|
|
||||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
|
||||||
// - Introduction, links and more at the top of imgui.cpp
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
|
||||||
#ifndef IMGUI_DISABLE
|
|
||||||
|
|
||||||
struct IDirect3DDevice9;
|
|
||||||
|
|
||||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
|
||||||
IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
|
|
||||||
|
|
||||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
|
||||||
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
|
|
||||||
|
|
||||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex);
|
|
||||||
|
|
||||||
#endif // #ifndef IMGUI_DISABLE
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user