Showing preview only (246K chars total). Download the full file or copy to clipboard to get everything.
Repository: netheril96/StaticJSON
Branch: master
Commit: 3f7a1f12bd6e
Files: 65
Total size: 227.8 KB
Directory structure:
gitextract_e730zr57/
├── .cmake-format.py
├── .github/
│ └── workflows/
│ └── ccpp.yaml
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── _clang-format
├── autojsoncxx/
│ ├── autojsoncxx.hpp
│ ├── autojsoncxx.py
│ ├── examples/
│ │ ├── failure/
│ │ │ ├── duplicate_key.json
│ │ │ ├── duplicate_key_user.json
│ │ │ ├── hard.json
│ │ │ ├── integer_string.json
│ │ │ ├── map_element_mismatch.json
│ │ │ ├── missing_required.json
│ │ │ ├── null_in_key.json
│ │ │ ├── out_of_range.json
│ │ │ ├── single_object.json
│ │ │ └── unknown_field.json
│ │ └── success/
│ │ ├── hard.json
│ │ ├── user_array.json
│ │ ├── user_array_compact.json
│ │ └── user_map.json
│ ├── userdef.hpp
│ └── userdef.json
├── cmake/
│ └── staticjson-config.cmake.in
├── examples/
│ ├── failure/
│ │ ├── duplicate_key.json
│ │ ├── duplicate_key_user.json
│ │ ├── hard.json
│ │ ├── integer_string.json
│ │ ├── invalid_enum.json
│ │ ├── map_element_mismatch.json
│ │ ├── missing_required.json
│ │ ├── null_in_key.json
│ │ ├── out_of_range.json
│ │ ├── single_object.json
│ │ ├── tensor_length_error.json
│ │ ├── tensor_type_mismatch.json
│ │ └── unknown_field.json
│ └── success/
│ ├── hard.json
│ ├── tensor.json
│ ├── user_array.json
│ ├── user_array_compact.json
│ └── user_map.json
├── format.sh
├── include/
│ └── staticjson/
│ ├── basic.hpp
│ ├── document.hpp
│ ├── enum.hpp
│ ├── error.hpp
│ ├── forward_declarations.hpp
│ ├── io.hpp
│ ├── optional_support.hpp
│ ├── primitive_types.hpp
│ ├── staticjson.hpp
│ └── stl_types.hpp
├── src/
│ └── staticjson.cpp
└── test/
├── myarray.hpp
├── test_autojsoncxx.cpp
├── test_basic.cpp
├── test_example.cpp
├── test_instantiation.cpp
├── test_integration.cpp
├── test_memory_usage.cpp
└── test_tensor.cpp
================================================
FILE CONTENTS
================================================
================================================
FILE: .cmake-format.py
================================================
# ----------------------------------
# Options affecting listfile parsing
# ----------------------------------
with section("parse"):
# Specify structure for custom cmake functions
additional_commands = { 'foo': { 'flags': ['BAR', 'BAZ'],
'kwargs': {'DEPENDS': '*', 'HEADERS': '*', 'SOURCES': '*'}}}
# Override configurations per-command where available
override_spec = {}
# Specify variable tags.
vartags = []
# Specify property tags.
proptags = []
# -----------------------------
# Options affecting formatting.
# -----------------------------
with section("format"):
# Disable formatting entirely, making cmake-format a no-op
disable = False
# How wide to allow formatted cmake files
line_width = 80
# How many spaces to tab for indent
tab_size = 2
# If true, lines are indented using tab characters (utf-8 0x09) instead of
# <tab_size> space characters (utf-8 0x20). In cases where the layout would
# require a fractional tab character, the behavior of the fractional
# indentation is governed by <fractional_tab_policy>
use_tabchars = False
# If <use_tabchars> is True, then the value of this variable indicates how
# fractional indentions are handled during whitespace replacement. If set to
# 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set
# to `round-up` fractional indentation is replaced with a single tab character
# (utf-8 0x09) effectively shifting the column to the next tabstop
fractional_tab_policy = 'use-space'
# If an argument group contains more than this many sub-groups (parg or kwarg
# groups) then force it to a vertical layout.
max_subgroups_hwrap = 2
# If a positional argument group contains more than this many arguments, then
# force it to a vertical layout.
max_pargs_hwrap = 6
# If a cmdline positional group consumes more than this many lines without
# nesting, then invalidate the layout (and nest)
max_rows_cmdline = 2
# If true, separate flow control names from their parentheses with a space
separate_ctrl_name_with_space = False
# If true, separate function names from parentheses with a space
separate_fn_name_with_space = False
# If a statement is wrapped to more than one line, than dangle the closing
# parenthesis on its own line.
dangle_parens = False
# If the trailing parenthesis must be 'dangled' on its on line, then align it
# to this reference: `prefix`: the start of the statement, `prefix-indent`:
# the start of the statement, plus one indentation level, `child`: align to
# the column of the arguments
dangle_align = 'prefix'
# If the statement spelling length (including space and parenthesis) is
# smaller than this amount, then force reject nested layouts.
min_prefix_chars = 4
# If the statement spelling length (including space and parenthesis) is larger
# than the tab width by more than this amount, then force reject un-nested
# layouts.
max_prefix_chars = 10
# If a candidate layout is wrapped horizontally but it exceeds this many
# lines, then reject the layout.
max_lines_hwrap = 2
# What style line endings to use in the output.
line_ending = 'unix'
# Format command names consistently as 'lower' or 'upper' case
command_case = 'canonical'
# Format keywords consistently as 'lower' or 'upper' case
keyword_case = 'unchanged'
# A list of command names which should always be wrapped
always_wrap = []
# If true, the argument lists which are known to be sortable will be sorted
# lexicographicall
enable_sort = True
# If true, the parsers may infer whether or not an argument list is sortable
# (without annotation).
autosort = False
# By default, if cmake-format cannot successfully fit everything into the
# desired linewidth it will apply the last, most agressive attempt that it
# made. If this flag is True, however, cmake-format will print error, exit
# with non-zero status code, and write-out nothing
require_valid_layout = False
# A dictionary mapping layout nodes to a list of wrap decisions. See the
# documentation for more information.
layout_passes = {}
# ------------------------------------------------
# Options affecting comment reflow and formatting.
# ------------------------------------------------
with section("markup"):
# What character to use for bulleted lists
bullet_char = '*'
# What character to use as punctuation after numerals in an enumerated list
enum_char = '.'
# If comment markup is enabled, don't reflow the first comment block in each
# listfile. Use this to preserve formatting of your copyright/license
# statements.
first_comment_is_literal = False
# If comment markup is enabled, don't reflow any comment block which matches
# this (regex) pattern. Default is `None` (disabled).
literal_comment_pattern = None
# Regular expression to match preformat fences in comments default=
# ``r'^\s*([`~]{3}[`~]*)(.*)$'``
fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$'
# Regular expression to match rulers in comments default=
# ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'``
ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$'
# If a comment line matches starts with this pattern then it is explicitly a
# trailing comment for the preceeding argument. Default is '#<'
explicit_trailing_pattern = '#<'
# If a comment line starts with at least this many consecutive hash
# characters, then don't lstrip() them off. This allows for lazy hash rulers
# where the first hash char is not separated by space
hashruler_min_length = 10
# If true, then insert a space between the first hash char and remaining hash
# chars in a hash ruler, and normalize its length to fill the column
canonicalize_hashrulers = True
# enable comment markup parsing and reflow
enable_markup = True
# ----------------------------
# Options affecting the linter
# ----------------------------
with section("lint"):
# a list of lint codes to disable
disabled_codes = []
# regular expression pattern describing valid function names
function_pattern = '[0-9a-z_]+'
# regular expression pattern describing valid macro names
macro_pattern = '[0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# (cache) scope
global_var_pattern = '[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# scope (but internal semantic)
internal_var_pattern = '_[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with local
# scope
local_var_pattern = '[a-z][a-z0-9_]+'
# regular expression pattern describing valid names for privatedirectory
# variables
private_var_pattern = '_[0-9a-z_]+'
# regular expression pattern describing valid names for public directory
# variables
public_var_pattern = '[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for function/macro
# arguments and loop variables.
argument_var_pattern = '[a-z][a-z0-9_]+'
# regular expression pattern describing valid names for keywords used in
# functions or macros
keyword_pattern = '[A-Z][0-9A-Z_]+'
# In the heuristic for C0201, how many conditionals to match within a loop in
# before considering the loop a parser.
max_conditionals_custom_parser = 2
# Require at least this many newlines between statements
min_statement_spacing = 1
# Require no more than this many newlines between statements
max_statement_spacing = 2
max_returns = 6
max_branches = 12
max_arguments = 5
max_localvars = 15
max_statements = 50
# -------------------------------
# Options affecting file encoding
# -------------------------------
with section("encode"):
# If true, emit the unicode byte-order mark (BOM) at the start of the file
emit_byteorder_mark = False
# Specify the encoding of the input file. Defaults to utf-8
input_encoding = 'utf-8'
# Specify the encoding of the output file. Defaults to utf-8. Note that cmake
# only claims to support utf-8 so be careful when using anything else
output_encoding = 'utf-8'
# -------------------------------------
# Miscellaneous configurations options.
# -------------------------------------
with section("misc"):
# A dictionary containing any per-command configuration overrides. Currently
# only `command_case` is supported.
per_command = {}
================================================
FILE: .github/workflows/ccpp.yaml
================================================
name: C/C++ CI
on: [push, pull_request]
env:
VERBOSE: 1
jobs:
build_matrix:
strategy:
matrix:
config:
[
[windows-latest, x64-windows, OFF],
[macos-latest, x64-osx, ON],
[ubuntu-20.04, x64-linux, ON],
]
runs-on: ${{ matrix.config[0] }}
steps:
- uses: actions/checkout@v1
- name: vcpkg build
uses: johnwason/vcpkg-action@v4
with:
pkgs: rapidjson catch2
triplet: ${{ matrix.config[1] }}
token: ${{ github.token }}
- name: configure
run: mkdir build && cd build && cmake -DSTATICJSON_ASAN=${{ matrix.config[2] }} -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=${{ matrix.config[1] }} ..
- name: build
run: cmake --build build --config Debug
- name: test
run: cd build && ctest -V -C Debug
================================================
FILE: .gitignore
================================================
.DS_Store
._*
xcode/
*.backup
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.appCMakeCache.txt
CMakeFiles
CMakeScripts
Makefile
cmake_install.cmake
install_manifest.txt
CTestTestfile.cmake
rapidjson.tgz
rapidjson*/
build/
.vscode/
================================================
FILE: .travis.yml
================================================
language: cpp
sudo: required
dist: trusty
script: "sudo apt-get install -y cmake && cmake . && make && ctest -V"
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.0)
project(StaticJSON)
option(STATICJSON_ENABLE_TEST "Enable building test for StaticJSON" ON)
option(STATICJSON_ASAN "Enable address sanitizer on non-MSVC" OFF)
set(CMAKE_CXX_STANDARD_REQUIRED 0)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()
if(MSVC)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS=1)
else()
if(STATICJSON_ASAN)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
endif()
endif()
find_path(RAPIDJSON_INCLUDE_DIR rapidjson/rapidjson.h)
set(SOURCE_FILES src/staticjson.cpp)
add_library(staticjson ${SOURCE_FILES})
set_property(TARGET staticjson PROPERTY CXX_STANDARD 11)
add_library(staticjson::staticjson ALIAS staticjson)
target_include_directories(
staticjson
PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/autojsoncxx>
$<BUILD_INTERFACE:${RAPIDJSON_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
if(STATICJSON_ENABLE_TEST)
set(TARGET test_staticjson)
file(GLOB SOURCES test/*.hpp test/*.cpp include/staticjson/*.hpp)
add_executable(${TARGET} ${SOURCES})
target_link_libraries(${TARGET} PRIVATE staticjson)
set_property(TARGET ${TARGET} PROPERTY CXX_STANDARD 17)
find_package(RapidJSON CONFIG REQUIRED)
target_link_libraries(${TARGET} PRIVATE rapidjson)
find_package(Catch2 CONFIG REQUIRED)
target_link_libraries(${TARGET} PRIVATE Catch2::Catch2 Catch2::Catch2WithMain)
enable_testing()
add_test(
NAME ${TARGET}
COMMAND ${TARGET}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/test)
endif()
include(GNUInstallDirs)
install(
TARGETS staticjson
EXPORT staticjson-targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/staticjson
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(
EXPORT staticjson-targets
FILE staticjson-targets.cmake
NAMESPACE staticjson::
DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/staticjson)
include(CMakePackageConfigHelpers)
configure_package_config_file(
${CMAKE_SOURCE_DIR}/cmake/staticjson-config.cmake.in
${CMAKE_BINARY_DIR}/cmake/staticjson-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/staticjson)
install(FILES ${CMAKE_BINARY_DIR}/cmake/staticjson-config.cmake
DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/staticjson)
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 Siyuan Ren (netheril96@gmail.com)
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.
================================================
FILE: README.md
================================================
# StaticJSON
Fast, direct and static typed parsing of JSON with C++.
## Overview
JSON is a popular format for data exchange. Reading and writing JSON in C++, however, is nontrivial. Even with the help of libraries, one still needs to write lots of boilerplate code, and it is extremely hard to guard against all possible errors, since JSON is dynamically typed while C++ employs static typing.
More importantly, manually writing such code is a violation of **DRY** principle. When manually written, the class definition, parsing and serialization code can easily become out of sync, leading to brittle code and subtle bugs.
`StaticJSON` is an attempt to solve this problem by automating such process.
## Usage
`StaticJSON` requires a C++11 compiler.
## Method 1: use [vcpkg](https://vcpkg.io)
Run command `vcpkg install staticjson`, then in your `CMakeLists.txt`, add
```cmake
find_package(staticjson CONFIG REQUIRED)
target_link_libraries(${YOUR_TARGET} PRIVATE staticjson::staticjson)
```
## Method 2: just build everything together
Just drop the `include` and `src` directory into your own project and build along with other sources. It requires you to separately install [`rapidjson`](https://rapidjson.org).
## Quick start
### Builtin types
```c++
#include <staticjson/staticjson.hpp>
int builtin_test() {
using namespace staticjson;
std::string a = to_json_string(std::vector<double>{1.0, 2.0, -3.1415});
std::string b = to_pretty_json_string(std::map<std::string, std::shared_ptr<std::list<bool>>>{});
std::vector<std::unordered_map<std::string, std::int64_t>> data;
const char* json_string = "[{\" hello \": 535353, \" world \": 849},"
" {\" k \": -548343}]";
assert(from_json_string(json_string, &data, nullptr));
assert(data.size() == 2);
assert(data[1][" k "] == -548343);
to_pretty_json_file(stdout, data);
return 0;
}
```
### Register custom class types
For your own classes, you need to add some definitions first before you can use the `from_json` and `to_json` functions. There are two ways of doing this.
#### Intrusive definition
This way requires you to implement a special method in the class prototyped `void staticjson_init(staticjson::ObjectHandler* h)`. Example definition
```c++
struct Date
{
int year, month, day;
void staticjson_init(ObjectHandler* h)
{
h->add_property("year", &year);
h->add_property("month", &month);
h->add_property("day", &day);
h->set_flags(Flags::DisallowUnknownKey);
}
};
struct BlockEvent
{
std::uint64_t serial_number, admin_ID = 255;
Date date;
std::string description, details;
void staticjson_init(ObjectHandler* h)
{
h->add_property("serial_number", &serial_number);
h->add_property("administrator ID", &admin_ID, Flags::Optional);
h->add_property("date", &date, Flags::Optional);
h->add_property("description", &description, Flags::Optional);
h->add_property("details", &details, Flags::Optional);
}
};
```
### Non-intrusive definition
This requires you to overload a special function for your custom class. For example, the `Date` overload is written as
```c++
namespace staticjson
{
void init(Date* d, ObjectHandler* h)
{
h->add_property("year", &d->year);
h->add_property("month", &d->month);
h->add_property("day", &d->day);
h->set_flags(Flags::DisallowUnknownKey);
}
}
```
You may need to declare `staticjson::init` as a friend function in order to access private and protected members.
### Register enumeration types
Example
```c++
enum class CalendarType
{
Gregorian,
Chinese,
Jewish,
Islam
};
STATICJSON_DECLARE_ENUM(CalendarType,
{"Gregorian", CalendarType::Gregorian},
{"Chinese", CalendarType::Chinese},
{"Jewish", CalendarType::Jewish},
{"Islam", CalendarType::Islam})
```
This will convert the enum type to/from strings, and signal error if the string is not in the list.
Note that this macro must not be instantiated inside a namespace.
## Custom conversion
If you want a type to be serialized in a different way, such as a custom `Date` object as an ISO8601 string or an arbitrary precision integer as a list of 32-bit integers, you can enable the custom conversion for the type. To do so, specialize the template class in namespace `staticjson`
```c++
namespace staticjson
{
template <>
struct Converter<Date>
{
typedef std::string shadow_type;
// This typedef is a must. The shadow type is a C++ type
// that can be directly converted to and from JSON values.
static std::unique_ptr<ErrorBase> from_shadow(const shadow_type& shadow, Date& value)
{
bool success = value.parseISO8601(shadow);
if (success)
return nullptr;
return std::make_unique<CustomError>("Invalid ISO 8601 string");
}
static void to_shadow(const Date& value, shadow_type& shadow)
{
shadow = value.toISO8601();
}
};
}
```
## Error handling
`StaticJSON` strives not to let any mismatch between the C++ type specifications and the JSON object slip. It detects and reports all kinds of errors, including type mismatch, integer out of range, floating number precision loss, required fields missing, duplicate keys etc. Many of them can be tuned on or off. It also reports an stack trace in case of error (not actual C++ exception).
The third parameter of all `from_json` family of functions is a nullable pointer to `staticjson::ParseStatus` object. If present, the error information will be dumped into it. An example error message is
```
Parsing failed at offset 1000 with error code 16:
Terminate parsing due to Handler error.
Traceback (last call first)
* Type mismatch between expected type "unsigned long long" and actual type "string"
* Error at object member with name "serial_number"
* Error at array element at index 0
* Error at object member with name "dark_history"
* Error at array element at index 1
```
## List of builtin supported types
* **Boolean types**: `bool`, `char`
* **Integer types**: `int`, `unsigned int`, `long`, `unsigned long`, `long long`, `unsigned long long`
* **Floating point types**: `float`, `double`
* **String types**: `std::string`
* **Array types**: `std::vector<•>`, `std::deque<•>`, `std::list<•>`, `std::array<•>`
* **Nullable types**: `std::nullptr_t`, `std::unique_ptr<•>`, `std::shared_ptr<•>`
* **Map types**: `std::{map, multimap, unordered_map, unordered_multimap}<std::string, •>`
* **Tuple types**: `std::tuple<...>`
## Dynamic typing
If you need occasional escape from the rigidity of C++'s static type system, but do not want complete dynamism, you can still find the middle ground in `StaticJSON`.
* You can embed a `staticjson::Document` (alias of `rapidjson::Document`) in your class/struct, which allows static typing for some class members and dynamic typing for others. Note `Document` is already nullable so do not use a smart pointer to `Document`.
* You can convert a `Document` or `Value` to and from a C++ type registered in `StaticJSON`. The functions are aptly named `from_json_value`, `from_json_document`, `to_json_value`, `to_json_document`.
## Export as JSON Schema
Function `export_json_schema` allows you to export the validation rules used by `StaticJSON` as JSON schema. It can then be used in other languages to do the similar validation. Note the two rules are only approximate match, because certain rules cannot be expressed in JSON schema yet, and because some languages have different treatments of numbers from C++.
## Misc
The project was originally named *autojsoncxx* and requires a code generator to run.
================================================
FILE: _clang-format
================================================
---
Language: Cpp
# BasedOnStyle: WebKit
AccessModifierOffset: -4
AlignAfterOpenBracket: true
AlignEscapedNewlinesLeft: false
AlignOperands: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
BinPackParameters: false
BinPackArguments: false
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: false
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: true
NamespaceIndentation: Inner
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
SpacesBeforeTrailingComments: 4
Cpp11BracedListStyle: true
Standard: Cpp11
IndentWidth: 4
TabWidth: 8
UseTab: Never
BreakBeforeBraces: Allman
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterCStyleCast: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
SpaceBeforeParens: ControlStatements
DisableFormat: false
FixNamespaceComments: false
...
================================================
FILE: autojsoncxx/autojsoncxx.hpp
================================================
#pragma once
#include <cstdio>
#include <staticjson/staticjson.hpp>
#include <string>
namespace autojsoncxx
{
using ParsingResult = staticjson::ParseStatus;
using staticjson::to_json_file;
using staticjson::to_json_string;
using staticjson::to_pretty_json_file;
using staticjson::to_pretty_json_string;
namespace error = staticjson::error;
template <class ValueType>
inline void to_json_string(std::string& output, const ValueType& value)
{
output = to_json_string(value);
}
template <class ValueType>
inline void to_pretty_json_string(std::string& output, const ValueType& value)
{
output = to_pretty_json_string(value);
}
template <class ValueType>
inline bool from_json_string(const char* str, ValueType& value, ParsingResult& err)
{
return staticjson::from_json_string(str, &value, &err);
}
template <class ValueType>
inline bool from_json_string(const std::string& str, ValueType& value, ParsingResult& err)
{
return staticjson::from_json_string(str.c_str(), &value, &err);
}
template <class ValueType>
inline bool from_json_file(const char* str, ValueType& value, ParsingResult& err)
{
return staticjson::from_json_file(str, &value, &err);
}
template <class ValueType>
inline bool from_json_file(const std::string& str, ValueType& value, ParsingResult& err)
{
return staticjson::from_json_file(str, &value, &err);
}
template <class ValueType>
inline bool from_json_file(std::FILE* fp, ValueType& value, ParsingResult& err)
{
return staticjson::from_json_file(fp, &value, &err);
}
template <class T>
void to_document(const T& value, rapidjson::Document& doc)
{
staticjson::to_json_document(&doc, value, nullptr);
}
template <class T>
bool from_document(T& value, const rapidjson::Document& doc, error::ErrorStack& errs)
{
staticjson::ParseStatus status;
bool rc = staticjson::from_json_document(doc, &value, &status);
if (status.has_error())
errs.swap(status.error_stack());
return rc;
}
}
================================================
FILE: autojsoncxx/autojsoncxx.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# The MIT License (MIT)
#
# Copyright (c) 2014 Siyuan Ren (netheril96@gmail.com)
#
# 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.
"""
This script allows easier transition from StaticJSON's precursor `autojsoncxx`.
Generates compatible C++ header files using StaticJSON's library.
"""
from __future__ import unicode_literals
from __future__ import print_function
import re
import argparse
import os
import string
import sys
import io
from numbers import Number
# Python 2/3 compatibility layer
is_python2 = sys.version_info.major == 2
if is_python2:
str = unicode
# simplejson has the same interface as the standard json module, but with better error messages
try:
import simplejson as json
except ImportError:
import json
# base class for all custom exceptions in this unit
class InvalidDefinitionError(Exception):
pass
class InvalidIdentifier(InvalidDefinitionError):
def __init__(self, identifier):
self.identifier = identifier
def __str__(self):
return "Invalid string for C++ identifier: " + repr(self.identifier)
class InvalidNamespace(InvalidDefinitionError):
def __init__(self, namespace):
self.namespace = namespace
def __str__(self):
return "Invalid namespace: " + repr(self.namespace)
class UnrecognizedOption(InvalidDefinitionError):
def __init__(self, option):
self.option = option
def __str__(self):
return "Unrecognized option: " + repr(self.option)
class UnsupportedTypeError(InvalidDefinitionError):
def __init__(self, type_name):
self.type_name = type_name
def __str__(self):
return "Unsupported C++ type: " + repr(self.type_name)
NOESCAPE_CHARACTERS = bytes(string.digits + string.ascii_letters + ' ', encoding='utf8')
def cstring_literal(byte_string):
"""convert arbitrary byte sequence into a C++ string literal by escaping every character"""
if all(c in NOESCAPE_CHARACTERS for c in byte_string):
return '"' + byte_string.decode() + '"'
return '"' + ''.join('\\x{:02x}'.format(ord(char)) for char in byte_string) + '"'
def check_identifier(identifier):
if not re.match(r'^[A-Za-z_]\w*$', identifier):
raise InvalidIdentifier(identifier)
class ClassInfo(object):
accept_options = {"name", "namespace", "parse_mode", "members", "constructor_code", "comment", "no_duplicates"}
def __init__(self, record):
self._name = record['name']
self._members = [MemberInfo(r) for r in record['members']]
self._strict = record.get('parse_mode', '') == 'strict'
self._namespace = record.get("namespace", None)
self._constructor_code = record.get("constructor_code", "")
self._no_duplicates = record.get("no_duplicates", False)
check_identifier(self._name)
if self._namespace is not None and not re.match(r'^(?:::)?[A-Za-z_]\w*(?:::[A-Za-z_]\w*)*$', self._namespace):
raise InvalidNamespace(self._namespace)
for op in record:
if op not in ClassInfo.accept_options:
raise UnrecognizedOption(op)
@property
def name(self):
return self._name
@property
def qualified_name(self):
if self.namespace is None:
return '::' + self.name
if self.namespace.startswith('::'):
return self.namespace + '::' + self.name
return '::' + self.namespace + '::' + self.name
@property
def members(self):
return self._members
@property
def strict_parsing(self):
return self._strict
@property
def namespace(self):
return self._namespace
@property
def constructor_code(self):
return self._constructor_code
@property
def no_duplicates(self):
return self._no_duplicates
class ClassDefinitionCodeGenerator(object):
def __init__(self, class_info):
self._class_info = class_info
@property
def class_info(self):
return self._class_info
def member_declarations(self):
return '\n'.join(m.type_name + ' ' + m.variable_name + ';' for m in self.class_info.members)
def initializer_list(self):
return ', '.join('{0}({1})'.format(m.variable_name, m.constructor_args) for m in self.class_info.members)
def constructor(self):
return 'explicit {name}():{init} {{ {code} }}\n'.format(name=self.class_info.name,
init=self.initializer_list(),
code=self.class_info.constructor_code)
def staticjson_init(self):
class_flags = 'staticjson::Flags::Default'
if not self.class_info.no_duplicates:
class_flags += ' | staticjson::Flags::AllowDuplicateKey'
if self.class_info.strict_parsing:
class_flags += ' | staticjson::Flags::DisallowUnknownKey'
return """
void staticjson_init(staticjson::ObjectHandler* h) {{
{member_flag_settings}
h->set_flags({class_flags});
}}
""".format(
class_flags=class_flags,
member_flag_settings=''.join(m.add_property_statement('h') for m in self.class_info.members)
)
def class_definition(self):
class_def = 'struct {name} {{\n {declarations}\n\n{constructor}\n{staticjson_init}\n \n}};' \
.format(name=self.class_info.name, declarations=self.member_declarations(),
constructor=self.constructor(),
staticjson_init=self.staticjson_init())
if self.class_info.namespace is not None:
for space in reversed(self.class_info.namespace.split('::')):
if space:
class_def = 'namespace {} {{ {} }}\n'.format(space, class_def)
return class_def
class MemberInfo(object):
accept_options = {'default', 'required', 'json_key', 'comment'}
def __init__(self, record):
self._record = record
if '*' in self.type_name or '&' in self.type_name:
raise UnsupportedTypeError(self.type_name)
check_identifier(self.variable_name)
if len(record) > 3:
raise UnrecognizedOption(record[3:])
if len(record) == 3:
for op in record[2]:
if op not in MemberInfo.accept_options:
raise UnrecognizedOption(op)
@property
def type_name(self):
return self._record[0]
@property
def variable_name(self):
return self._record[1]
@property
def json_key(self):
try:
return self._record[2]['json_key'].encode('utf-8')
except (IndexError, KeyError):
return self.variable_name.encode('utf-8')
@property
def is_required(self):
try:
return self._record[2]['required']
except (IndexError, KeyError):
return False
@property
def default(self):
try:
return self._record[2]['default']
except (IndexError, KeyError):
return None
@property
def constructor_args(self):
return MemberInfo.cpp_repr(self.default)
def add_property_statement(self, handler_name):
return '{}->add_property({}, &this->{}, {});\n'.format(
handler_name, cstring_literal(self.json_key), self.variable_name,
'staticjson::Flags::Default' if self.is_required else 'staticjson::Flags::Optional')
@staticmethod
def cpp_repr(args):
if args is None:
return ''
elif args is True:
return 'true'
elif args is False:
return 'false'
elif isinstance(args, str):
return cstring_literal(args.encode('utf-8'))
elif isinstance(args, Number):
return str(args)
elif isinstance(args, bytes):
return cstring_literal(args)
else:
raise UnrecognizedOption("default=" + repr(args))
def read_utf8(filename):
with io.open(filename, 'rt', encoding='utf-8') as f:
text = f.read()
if text.startswith(u'\ufeff'): # Skip BOM
text = text[1:]
return text
def main():
parser = argparse.ArgumentParser(description='`autojsoncxx` code generator (compatibility mode)\n'
'(visit https://github.com/netheril96/StaticJSON for details)')
parser.add_argument('-c', '--check', help='Compatibility flag; does nothing',
action='store_true', default=False)
parser.add_argument('-i', '--input', help='input name for the definition file for classes', required=True)
parser.add_argument('-o', '--output', help='output name for the header file', default=None)
parser.add_argument('--template', help='Compatibility flag; does nothing', default=None)
args = parser.parse_args()
if args.output is None:
args.output = os.path.basename(args.input)
args.output = os.path.splitext(args.output)[0] + '.hpp'
raw_record = json.loads(read_utf8(args.input))
with io.open(args.output, 'w', encoding='utf-8') as output:
output.write('#pragma once\n\n')
def output_class(class_record):
output.write(ClassDefinitionCodeGenerator(ClassInfo(class_record)).class_definition())
output.write('\n\n')
if isinstance(raw_record, list):
for r in raw_record:
output_class(r)
else:
output_class(raw_record)
if __name__ == '__main__':
main()
================================================
FILE: autojsoncxx/examples/failure/duplicate_key.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C",
"note": "the duplicate key error only occurs if your map types does not support duplicate key, e.g. `std::map`"
}
}
]
================================================
FILE: autojsoncxx/examples/failure/duplicate_key_user.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"ID": 3399510046441,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: autojsoncxx/examples/failure/hard.json
================================================
[{"serial_number": 90049710466114, "details": "unknown"}, -65535, null, 2.718281828459045, {"Second": {"ID": 13478355757133566847, "optional_attributes": {"Open ID": "something@somewhere.com", "Self description": "Can you handle characters above Basic Multilingual Plane?\ud83d\ude04\ud83c\udf85 \ud83c\udf81\ud83d\udc31\u2708\ufe0f\ud83d\udc18\ud83d\udd22\ud840\udc46\ud841\udf7b\ud844\udfa6\ud844\udf20", "Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"}, "block_event": null, "Third": null, "dark_history": [{"date": {"month": 3, "day": 8, "year": 2013}, "serial_number": 11932018656737597978, "details": null, "administrator ID": 8027685536805674999, "description": "copyright infringement"}], "birthday": {"month": 1, "day": 23, "year": 2001}, "nickname": "\u2192\u261b\u2205\u2206\u2135"}, "First": {"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`", "ID": 7947402710862746952, "nickname": "bigger than bigger", "birthday": {"month": 9, "day": 2, "year": 1984}, "block_event": {"date": {"month": 12, "day": 31, "year": 1970}, "serial_number": 9097588792683265916, "details": "most likely a troll", "administrator ID": 10720293540521355122, "description": "advertisement"}}}, false]
================================================
FILE: autojsoncxx/examples/failure/integer_string.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": "0xa5970bbff02d9a1a",
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: autojsoncxx/examples/failure/map_element_mismatch.json
================================================
{
"First": {
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
"Second": {
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
},
"Third": false
}
================================================
FILE: autojsoncxx/examples/failure/missing_required.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
}
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: autojsoncxx/examples/failure/null_in_key.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year\u0000 I am invisible because I am behind a null": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: autojsoncxx/examples/failure/out_of_range.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 162751169614016163
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: autojsoncxx/examples/failure/single_object.json
================================================
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
}
}
================================================
FILE: autojsoncxx/examples/failure/unknown_field.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31,
"hour": 21,
"minute": 33,
"second": 2
},
"description": "advertisement",
"details": "most likely a troll"
}
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: autojsoncxx/examples/success/hard.json
================================================
[{"serial_number": 90049710466114, "details": "unknown"}, -65535, null, 2.718281828459045, {"Second": {"ID": 13478355757133566847, "optional_attributes": {"Open ID": "something@somewhere.com", "Self description": "Can you handle characters above Basic Multilingual Plane?\ud83d\ude04\ud83c\udf85 \ud83c\udf81\ud83d\udc31\u2708\ufe0f\ud83d\udc18\ud83d\udd22\ud840\udc46\ud841\udf7b\ud844\udfa6\ud844\udf20", "Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"}, "block_event": null, "Third": null, "dark_history": [{"date": {"month": 3, "day": 8, "year": 2013}, "serial_number": 11932018656737597978, "details": "", "administrator ID": 8027685536805674999, "description": "copyright infringement"}], "birthday": {"month": 1, "day": 23, "year": 2001}, "nickname": "\u2192\u261b\u2205\u2206\u2135"}, "First": {"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`", "ID": 7947402710862746952, "nickname": "bigger than bigger", "birthday": {"month": 9, "day": 2, "year": 1984}, "block_event": {"date": {"month": 12, "day": 31, "year": 1970}, "serial_number": 9097588792683265916, "details": "most likely a troll", "administrator ID": 10720293540521355122, "description": "advertisement"}}}, false]
================================================
FILE: autojsoncxx/examples/success/user_array.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: autojsoncxx/examples/success/user_array_compact.json
================================================
[{"ID":7947402710862746952,"nickname":"bigger than bigger","birthday":{"year":1984,"month":9,"day":2},"block_event":{"serial_number":9097588792683265916,"administrator ID":10720293540521355122,"date":{"year":1970,"month":12,"day":31},"description":"advertisement","details":"most likely a troll"},"dark_history":[],"optional_attributes":{}},{"ID":13478355757133566847,"nickname":"→☛∅∆ℵ","birthday":{"year":2001,"month":1,"day":23},"block_event":null,"dark_history":[{"serial_number":11932018656737597978,"administrator ID":8027685536805674999,"date":{"year":2013,"month":3,"day":8},"description":"copyright infringement","details":""}],"optional_attributes":{"Auth-Token":"45F13704-A60D-4D44-B161-89BAB88E528C","Open ID":"something@somewhere.com","Self description":"Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠"}}]
================================================
FILE: autojsoncxx/examples/success/user_map.json
================================================
{
"First": {
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
"Second": {
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
}
================================================
FILE: autojsoncxx/userdef.hpp
================================================
#pragma once
namespace config
{
struct Date
{
int year;
int month;
int day;
explicit Date() : year(), month(), day() {}
void staticjson_init(staticjson::ObjectHandler* h)
{
h->add_property("year", &this->year, staticjson::Flags::Default);
h->add_property("month", &this->month, staticjson::Flags::Default);
h->add_property("day", &this->day, staticjson::Flags::Default);
h->set_flags(staticjson::Flags::Default | staticjson::Flags::AllowDuplicateKey
| staticjson::Flags::DisallowUnknownKey);
}
};
}
namespace config
{
namespace event
{
struct BlockEvent
{
unsigned long long serial_number;
unsigned long long admin_ID;
Date date;
std::string description;
std::string details;
explicit BlockEvent()
: serial_number()
, admin_ID(255)
, date()
, description("\x2f\x2a\x20\x69\x6e\x69\x74\x20\x2a\x2f\x20\x74\x72\x79\x69\x6e\x67\x20"
"\x74\x6f\x20\x6d\x65\x73\x73\x20\x75\x70\x20\x77\x69\x74\x68\x20\x74\x68"
"\x65\x20\x63\x6f\x64\x65\x20\x67\x65\x6e\x65\x72\x61\x74\x6f\x72")
, details()
{
date.year = 1970;
date.month = 1;
date.day = 1; /* Assign date to the UNIX epoch */
}
void staticjson_init(staticjson::ObjectHandler* h)
{
h->add_property("\x73\x65\x72\x69\x61\x6c\x5f\x6e\x75\x6d\x62\x65\x72",
&this->serial_number,
staticjson::Flags::Default);
h->add_property("administrator ID", &this->admin_ID, staticjson::Flags::Optional);
h->add_property("date", &this->date, staticjson::Flags::Optional);
h->add_property("description", &this->description, staticjson::Flags::Optional);
h->add_property("details", &this->details, staticjson::Flags::Optional);
h->set_flags(staticjson::Flags::Default | staticjson::Flags::AllowDuplicateKey);
}
};
}
}
namespace config
{
struct User
{
unsigned long long ID;
std::string nickname;
Date birthday;
std::shared_ptr<config::event::BlockEvent> block_event;
std::vector<config::event::BlockEvent> dark_history;
std::map<std::string, std::string> optional_attributes;
explicit User()
: ID()
, nickname("\xe2\x9d\xb6\xe2\x9d\xb7\xe2\x9d\xb8")
, birthday()
, block_event()
, dark_history()
, optional_attributes()
{
}
void staticjson_init(staticjson::ObjectHandler* h)
{
h->add_property("ID", &this->ID, staticjson::Flags::Default);
h->add_property("nickname", &this->nickname, staticjson::Flags::Default);
h->add_property("birthday", &this->birthday, staticjson::Flags::Optional);
h->add_property("\x62\x6c\x6f\x63\x6b\x5f\x65\x76\x65\x6e\x74",
&this->block_event,
staticjson::Flags::Optional);
h->add_property("\x64\x61\x72\x6b\x5f\x68\x69\x73\x74\x6f\x72\x79",
&this->dark_history,
staticjson::Flags::Optional);
h->add_property(
"\x6f\x70\x74\x69\x6f\x6e\x61\x6c\x5f\x61\x74\x74\x72\x69\x62\x75\x74\x65\x73",
&this->optional_attributes,
staticjson::Flags::Optional);
h->set_flags(staticjson::Flags::Default);
}
};
}
================================================
FILE: autojsoncxx/userdef.json
================================================
[
{
"name": "Date",
"namespace": "config",
"parse_mode": "strict",
"members": [
["int", "year", {"required": true}],
["int", "month", {"required": true}],
["int", "day", {"required": true}]
]
},
{
"name": "BlockEvent",
"namespace": "config::event",
"members": [
["unsigned long long", "serial_number", {"required": true}],
["unsigned long long", "admin_ID", {"json_key": "administrator ID", "default": 255}],
["Date", "date"],
["std::string", "description", {"default": "/* init */ trying to mess up with the code generator"}],
["std::string", "details"]
],
"constructor_code": "date.year = 1970; date.month = 1; date.day = 1; /* Assign date to the UNIX epoch */"
},
{
"name": "User",
"namespace": "config",
"no_duplicates": true,
"members": [
["unsigned long long", "ID", {"required": true}],
["std::string", "nickname", {"required": true, "default": "❶❷❸"} ],
["Date", "birthday"],
["std::shared_ptr<config::event::BlockEvent>", "block_event"],
["std::vector<config::event::BlockEvent>", "dark_history"],
["std::map<std::string, std::string>", "optional_attributes"]
]
}
]
================================================
FILE: cmake/staticjson-config.cmake.in
================================================
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(rapidjson CONFIG)
if(NOT TARGET staticjson::staticjson)
include(${CMAKE_CURRENT_LIST_DIR}/staticjson-targets.cmake)
endif()
================================================
FILE: examples/failure/duplicate_key.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C",
"note": "the duplicate key error only occurs if your map types does not support duplicate key, e.g. `std::map`"
}
}
]
================================================
FILE: examples/failure/duplicate_key_user.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"ID": 3399510046441,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: examples/failure/hard.json
================================================
[{"serial_number": 90049710466114, "details": "unknown"}, -65535, null, 2.718281828459045, {"Second": {"ID": 13478355757133566847, "optional_attributes": {"Open ID": "something@somewhere.com", "Self description": "Can you handle characters above Basic Multilingual Plane?\ud83d\ude04\ud83c\udf85 \ud83c\udf81\ud83d\udc31\u2708\ufe0f\ud83d\udc18\ud83d\udd22\ud840\udc46\ud841\udf7b\ud844\udfa6\ud844\udf20", "Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"}, "block_event": null, "Third": null, "dark_history": [{"date": {"month": 3, "day": 8, "year": 2013}, "serial_number": 11932018656737597978, "details": null, "administrator ID": 8027685536805674999, "description": "copyright infringement"}], "birthday": {"month": 1, "day": 23, "year": 2001}, "nickname": "\u2192\u261b\u2205\u2206\u2135"}, "First": {"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`", "ID": 7947402710862746952, "nickname": "bigger than bigger", "birthday": {"month": 9, "day": 2, "year": 1984}, "block_event": {"date": {"month": 12, "day": 31, "year": 1970}, "serial_number": 9097588792683265916, "details": "most likely a troll", "administrator ID": 10720293540521355122, "description": "advertisement"}}}, false]
================================================
FILE: examples/failure/integer_string.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": "0xa5970bbff02d9a1a",
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: examples/failure/invalid_enum.json
================================================
{
"First": {
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"dark_event": {
"serial_number": 9876543210123456789,
"administrator ID": 11223344556677889900,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "promote",
"details": "at least like a troll",
"flags": null
},
"alternate_history": [
null,
{
"serial_number": 1123581321345589,
"administrator ID": 1123581321345589,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "redacted",
"details": "redacted",
"flags": "x"
}
],
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
"Second": {
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8,
"type": "West"
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
}
================================================
FILE: examples/failure/map_element_mismatch.json
================================================
{
"First": {
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
"Second": {
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
},
"Third": false
}
================================================
FILE: examples/failure/missing_required.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
}
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: examples/failure/null_in_key.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year\u0000 I am invisible because I am behind a null": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: examples/failure/out_of_range.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 162751169614016163
},
"description": "advertisement",
"details": "most likely a troll"
},
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: examples/failure/single_object.json
================================================
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
}
}
================================================
FILE: examples/failure/tensor_length_error.json
================================================
[
[]
]
================================================
FILE: examples/failure/tensor_type_mismatch.json
================================================
[
["1", 2, 3]
]
================================================
FILE: examples/failure/unknown_field.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31,
"hour": 21,
"minute": 33,
"second": 2
},
"description": "advertisement",
"details": "most likely a troll"
}
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
]
================================================
FILE: examples/success/hard.json
================================================
[{"serial_number": 90049710466114, "details": "unknown"}, -65535, null, 2.718281828459045, {"Second": {"ID": 13478355757133566847, "optional_attributes": {"Open ID": "something@somewhere.com", "Self description": "Can you handle characters above Basic Multilingual Plane?\ud83d\ude04\ud83c\udf85 \ud83c\udf81\ud83d\udc31\u2708\ufe0f\ud83d\udc18\ud83d\udd22\ud840\udc46\ud841\udf7b\ud844\udfa6\ud844\udf20", "Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"}, "block_event": null, "Third": null, "dark_history": [{"date": {"month": 3, "day": 8, "year": 2013}, "serial_number": 11932018656737597978, "details": "", "administrator ID": 8027685536805674999, "description": "copyright infringement"}], "birthday": {"month": 1, "day": 23, "year": 2001}, "nickname": "\u2192\u261b\u2205\u2206\u2135"}, "First": {"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`", "ID": 7947402710862746952, "nickname": "bigger than bigger", "birthday": {"month": 9, "day": 2, "year": 1984}, "block_event": {"date": {"month": 12, "day": 31, "year": 1970}, "serial_number": 9097588792683265916, "details": "most likely a troll", "administrator ID": 10720293540521355122, "description": "advertisement"}}}, false]
================================================
FILE: examples/success/tensor.json
================================================
[
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 0]
],
[
[1.0, 2.0],
[3.0, 4.0],
[5.0, 6.0]
],
[
[4.44],
[0.9],
[8.024]
],
[[], [], []]
]
================================================
FILE: examples/success/user_array.json
================================================
[
{
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2,
"type": "Jewish"
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31,
"type": "Chinese"
},
"description": "advertisement",
"details": "most likely a troll"
},
"dark_event": {
"serial_number": 9876543210123456789,
"administrator ID": 11223344556677889900,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "promote",
"details": "at least like a troll",
"flags": null
},
"alternate_history": [
null,
{
"serial_number": 1123581321345589,
"administrator ID": 1123581321345589,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "redacted",
"details": "redacted",
"flags": "x"
}
],
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
{
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
},
{
"ID": 994851,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 75350019499420,
"administrator ID": 1072029354,
"date": {
"year": 1993,
"month": 9,
"day": 7
},
"description": "advertisement",
"details": "hehe"
},
"auxiliary": [
3, [[4.0, 5.0], [9.2, 3.3]], true
]
}
]
================================================
FILE: examples/success/user_array_compact.json
================================================
[{"ID":7947402710862746952,"nickname":"bigger than bigger","birthday":{"year":1984,"month":9,"day":2},"block_event":{"serial_number":9097588792683265916,"administrator ID":10720293540521355122,"date":{"year":1970,"month":12,"day":31},"description":"advertisement","details":"most likely a troll"},"dark_history":[],"optional_attributes":{}},{"ID":13478355757133566847,"nickname":"→☛∅∆ℵ","birthday":{"year":2001,"month":1,"day":23},"block_event":null,"dark_history":[{"serial_number":11932018656737597978,"administrator ID":8027685536805674999,"date":{"year":2013,"month":3,"day":8},"description":"copyright infringement","details":""}],"optional_attributes":{"Auth-Token":"45F13704-A60D-4D44-B161-89BAB88E528C","Open ID":"something@somewhere.com","Self description":"Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠"}}]
================================================
FILE: examples/success/user_map.json
================================================
{
"First": {
"ID": 7947402710862746952,
"nickname": "bigger than bigger",
"birthday": {
"year": 1984,
"month": 9,
"day": 2
},
"block_event": {
"serial_number": 9097588792683265916,
"administrator ID": 10720293540521355122,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "advertisement",
"details": "most likely a troll"
},
"dark_event": {
"serial_number": 9876543210123456789,
"administrator ID": 11223344556677889900,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "promote",
"details": "at least like a troll",
"flags": null
},
"alternate_history": [
null,
{
"serial_number": 1123581321345589,
"administrator ID": 1123581321345589,
"date": {
"year": 1970,
"month": 12,
"day": 31
},
"description": "redacted",
"details": "redacted",
"flags": "x"
}
],
"comment": "This field is not specified by our class; but it is silently skipped because the parse_mode of class `User` is not `strict`"
},
"Second": {
"ID": 13478355757133566847,
"nickname": "→☛∅∆ℵ",
"birthday": {
"year": 2001,
"month": 1,
"day": 23
},
"block_event": null,
"dark_history": [
{
"serial_number": 11932018656737597978,
"administrator ID": 8027685536805674999,
"date": {
"year": 2013,
"month": 3,
"day": 8
},
"description": "copyright infringement",
"details": ""
}
],
"optional_attributes": {
"Self description": "Can you handle characters above Basic Multilingual Plane?😄🎅 🎁🐱✈️🐘🔢𠁆𠝻𡎦𡌠",
"Open ID": "something@somewhere.com",
"Auth-Token": "45F13704-A60D-4D44-B161-89BAB88E528C"
}
}
}
================================================
FILE: format.sh
================================================
#!/bin/sh
cd $(dirname $0)
GLOBIGNORE="include/staticjson/optional_support.hpp"
clang-format -i --style=File autojsoncxx/*.hpp include/staticjson/*.hpp src/*.cpp test/*.cpp test/myarray.hpp
================================================
FILE: include/staticjson/basic.hpp
================================================
#pragma once
#include <rapidjson/document.h>
#include <staticjson/error.hpp>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <stack>
#include <type_traits>
namespace staticjson
{
struct NonMobile
{
NonMobile() {}
~NonMobile() {}
NonMobile(const NonMobile&) = delete;
NonMobile(NonMobile&&) = delete;
NonMobile& operator=(const NonMobile&) = delete;
NonMobile& operator=(NonMobile&&) = delete;
};
typedef unsigned int SizeType;
// This class is not thread safe, so please set all values at startup or when single threaded.
class GlobalConfig : private NonMobile
{
public:
static GlobalConfig* getInstance() noexcept;
SizeType getMemoryChunkSize() const noexcept { return memoryChunkSize; }
void setMemoryChunkSize(SizeType value) noexcept { memoryChunkSize = value; }
void setMaxLeaves(SizeType maxNum) noexcept
{
maxLeaves = maxNum;
_isMaxLeavesSet = true;
}
void setMaxDepth(SizeType maxDep) noexcept
{
maxDepth = maxDep;
_isMaxDepthSet = true;
}
SizeType getMaxDepth() const noexcept { return maxDepth; }
SizeType getMaxLeaves() const noexcept { return maxLeaves; }
bool isMaxLeavesSet() const noexcept { return _isMaxLeavesSet; }
bool isMaxDepthSet() const noexcept { return _isMaxDepthSet; }
void unsetMaxLeavesFlag() noexcept
{
_isMaxLeavesSet = false;
maxLeaves = UINT_MAX;
}
void unsetMaxDepthFlag() noexcept
{
_isMaxDepthSet = false;
maxDepth = UINT_MAX;
}
private:
GlobalConfig() {}
bool _isMaxLeavesSet = false;
bool _isMaxDepthSet = false;
SizeType maxLeaves = UINT_MAX;
SizeType maxDepth = UINT_MAX;
SizeType memoryChunkSize = 1000;
};
class IHandler
{
public:
IHandler() {}
virtual ~IHandler();
virtual bool Null() = 0;
virtual bool Bool(bool) = 0;
virtual bool Int(int) = 0;
virtual bool Uint(unsigned) = 0;
virtual bool Int64(std::int64_t) = 0;
virtual bool Uint64(std::uint64_t) = 0;
virtual bool Double(double) = 0;
virtual bool String(const char*, SizeType, bool) = 0;
virtual bool StartObject() = 0;
virtual bool Key(const char*, SizeType, bool) = 0;
virtual bool EndObject(SizeType) = 0;
virtual bool StartArray() = 0;
virtual bool EndArray(SizeType) = 0;
virtual bool RawNumber(const char*, SizeType, bool);
virtual void prepare_for_reuse() = 0;
};
using rapidjson::Document;
using rapidjson::Value;
typedef rapidjson::MemoryPoolAllocator<> MemoryPoolAllocator;
class BaseHandler : public IHandler, private NonMobile
{
friend class NullableHandler;
protected:
std::unique_ptr<ErrorBase> the_error;
bool parsed = false;
protected:
bool set_out_of_range(const char* actual_type);
bool set_type_mismatch(const char* actual_type);
virtual void reset() {}
public:
BaseHandler() {}
virtual ~BaseHandler();
virtual std::string type_name() const = 0;
virtual bool Null() override { return set_type_mismatch("null"); }
virtual bool Bool(bool) override { return set_type_mismatch("bool"); }
virtual bool Int(int) override { return set_type_mismatch("int"); }
virtual bool Uint(unsigned) override { return set_type_mismatch("unsigned"); }
virtual bool Int64(std::int64_t) override { return set_type_mismatch("int64_t"); }
virtual bool Uint64(std::uint64_t) override { return set_type_mismatch("uint64_t"); }
virtual bool Double(double) override { return set_type_mismatch("double"); }
virtual bool String(const char*, SizeType, bool) override
{
return set_type_mismatch("string");
}
virtual bool StartObject() override { return set_type_mismatch("object"); }
virtual bool Key(const char*, SizeType, bool) override { return set_type_mismatch("object"); }
virtual bool EndObject(SizeType) override { return set_type_mismatch("object"); }
virtual bool StartArray() override { return set_type_mismatch("array"); }
virtual bool EndArray(SizeType) override { return set_type_mismatch("array"); }
virtual bool has_error() const { return bool(the_error); }
virtual bool reap_error(ErrorStack& errs)
{
if (!the_error)
return false;
errs.push(the_error.release());
return true;
}
bool is_parsed() const { return parsed; }
void prepare_for_reuse() override
{
the_error.reset();
parsed = false;
reset();
}
virtual bool write(IHandler* output) const = 0;
virtual void generate_schema(Value& output, MemoryPoolAllocator& alloc) const = 0;
};
struct Flags
{
static const unsigned Default = 0x0, AllowDuplicateKey = 0x1, Optional = 0x2, IgnoreRead = 0x4,
IgnoreWrite = 0x8, DisallowUnknownKey = 0x10;
};
// Forward declaration
template <class T>
class Handler;
namespace mempool
{
[[noreturn]] void throw_bad_alloc();
rapidjson::CrtAllocator& get_crt_allocator() noexcept;
template <class T>
class PooledAllocator
{
private:
MemoryPoolAllocator* pool;
template <class U>
friend class PooledAllocator;
public:
using value_type = T;
using propagate_on_container_copy_assignment = std::true_type;
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
explicit PooledAllocator(MemoryPoolAllocator* pool) noexcept : pool(pool) {}
template <class U>
PooledAllocator(const PooledAllocator<U>& other) noexcept : pool(other.pool)
{
}
template <class U>
bool operator==(const PooledAllocator<U>& other) const noexcept
{
return pool == other.pool;
}
template <class U>
bool operator!=(const PooledAllocator<U>& other) const noexcept
{
return pool != other.pool;
}
T* allocate(const size_t n) const
{
if (!n)
{
return nullptr;
}
auto ptr = static_cast<T*>(pool->Malloc(n * sizeof(T)));
if (!ptr)
{
throw_bad_alloc();
}
return ptr;
}
void deallocate(T* const p, size_t) const noexcept
{
if (p)
{
pool->Free(p);
}
}
};
template <class K, class V>
using Map = std::map<K, V, std::less<K>, PooledAllocator<std::pair<const K, V>>>;
template <class T>
using Stack = std::stack<T, std::deque<T, PooledAllocator<T>>>;
using String = std::basic_string<char, std::char_traits<char>, PooledAllocator<char>>;
inline std::string to_std_string(const String& str) { return {str.data(), str.size()}; }
template <class T>
struct PooledDeleter
{
void operator()(T* ptr) const noexcept
{
if (!ptr)
{
return;
}
ptr->~T();
static_assert(!MemoryPoolAllocator::kNeedFree,
"MemoryPoolAllocator must not need freeing");
}
};
template <class T>
using UniquePtr = std::unique_ptr<T, PooledDeleter<T>>;
template <typename T, typename... Args>
T* pooled_new(MemoryPoolAllocator& pool, Args&&... args)
{
auto storage = pool.Malloc(sizeof(T));
static_assert(!MemoryPoolAllocator::kNeedFree,
"MemoryPoolAllocator must not need freeing or we will need to handle "
"potential exceptions in the construction of T");
new (storage) T(std::forward<Args>(args)...);
return static_cast<T*>(storage);
}
}
class ObjectHandler : public BaseHandler
{
protected:
struct FlaggedHandler
{
mempool::UniquePtr<BaseHandler> handler;
unsigned flags;
};
protected:
MemoryPoolAllocator memory_pool_allocator;
mempool::Map<mempool::String, FlaggedHandler> internals;
FlaggedHandler* current = nullptr;
mempool::String current_name;
int depth = 0;
unsigned flags = Flags::Default;
unsigned int jsonDepth = 0;
// true if last symbol is '[', otherwise false
bool lastLeafStat = false;
SizeType totalLeaves = 0;
// save the number of object or array
mempool::Stack<SizeType> leavesStack;
protected:
void postinit();
bool precheck(const char* type);
bool postcheck(bool success);
void set_missing_required(const std::string& name);
void add_handler(mempool::String&&, FlaggedHandler&&);
void reset() override;
private:
bool StartCheckMaxDepthMaxLeaves(bool isArray);
bool EndCheckMaxDepthMaxLeaves(SizeType sz, bool isArray);
template <class T>
void add_property(mempool::String name, T* pointer, unsigned flags_ = Flags::Default)
{
FlaggedHandler fh;
fh.handler.reset(mempool::pooled_new<Handler<T>>(memory_pool_allocator, pointer));
fh.flags = flags_;
add_handler(std::move(name), std::move(fh));
}
public:
ObjectHandler();
~ObjectHandler();
std::string type_name() const override;
virtual bool Null() override;
virtual bool Bool(bool) override;
virtual bool Int(int) override;
virtual bool Uint(unsigned) override;
virtual bool Int64(std::int64_t) override;
virtual bool Uint64(std::uint64_t) override;
virtual bool Double(double) override;
virtual bool String(const char*, SizeType, bool) override;
virtual bool StartObject() override;
virtual bool Key(const char*, SizeType, bool) override;
virtual bool EndObject(SizeType) override;
virtual bool StartArray() override;
virtual bool EndArray(SizeType) override;
virtual bool reap_error(ErrorStack&) override;
virtual bool write(IHandler* output) const override;
virtual void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override;
unsigned get_flags() const { return flags; }
void set_flags(unsigned f) { flags = f; }
const MemoryPoolAllocator& get_memory_pool() const noexcept { return memory_pool_allocator; }
template <class T>
void add_property(const std::string& name, T* pointer, unsigned flags_ = Flags::Default)
{
add_property(mempool::String(name.data(),
name.size(),
mempool::String::allocator_type(&memory_pool_allocator)),
pointer,
flags_);
}
template <class T>
void add_property(const char* name, T* pointer, unsigned flags_ = Flags::Default)
{
add_property(mempool::String(name, mempool::String::allocator_type(&memory_pool_allocator)),
pointer,
flags_);
}
};
template <class T>
struct Converter
{
typedef T shadow_type;
static std::unique_ptr<ErrorBase> from_shadow(const shadow_type& shadow, T& value)
{
(void)shadow;
(void)value;
return nullptr;
}
static void to_shadow(const T& value, shadow_type& shadow)
{
(void)shadow;
(void)value;
}
static std::string type_name() { return "T"; }
static constexpr bool has_specialized_type_name = false;
};
template <class T>
void init(T* t, ObjectHandler* h)
{
t->staticjson_init(h);
}
template <class T>
class ObjectTypeHandler : public ObjectHandler
{
public:
explicit ObjectTypeHandler(T* t)
{
init(t, this);
postinit();
}
};
template <class T>
class ConversionHandler : public BaseHandler
{
private:
typedef typename Converter<T>::shadow_type shadow_type;
typedef Handler<shadow_type> internal_type;
private:
shadow_type shadow;
internal_type internal;
T* m_value;
protected:
bool postprocess(bool success)
{
if (!success)
{
return false;
}
if (!internal.is_parsed())
return true;
this->parsed = true;
auto err = Converter<T>::from_shadow(shadow, *m_value);
if (err)
{
this->the_error.swap(err);
return false;
}
return true;
}
void reset() override
{
shadow = shadow_type();
internal.prepare_for_reuse();
}
public:
explicit ConversionHandler(T* t) : shadow(), internal(&shadow), m_value(t) {}
std::string type_name() const override
{
// if (Converter<T>::has_specialized_type_name)
// return Converter<T>::type_name();
return internal.type_name();
}
virtual bool Null() override { return postprocess(internal.Null()); }
virtual bool Bool(bool b) override { return postprocess(internal.Bool(b)); }
virtual bool Int(int i) override { return postprocess(internal.Int(i)); }
virtual bool Uint(unsigned u) override { return postprocess(internal.Uint(u)); }
virtual bool Int64(std::int64_t i) override { return postprocess(internal.Int64(i)); }
virtual bool Uint64(std::uint64_t u) override { return postprocess(internal.Uint64(u)); }
virtual bool Double(double d) override { return postprocess(internal.Double(d)); }
virtual bool String(const char* str, SizeType size, bool copy) override
{
return postprocess(internal.String(str, size, copy));
}
virtual bool StartObject() override { return postprocess(internal.StartObject()); }
virtual bool Key(const char* str, SizeType size, bool copy) override
{
return postprocess(internal.Key(str, size, copy));
}
virtual bool EndObject(SizeType sz) override { return postprocess(internal.EndObject(sz)); }
virtual bool StartArray() override { return postprocess(internal.StartArray()); }
virtual bool EndArray(SizeType sz) override { return postprocess(internal.EndArray(sz)); }
virtual bool has_error() const override
{
return BaseHandler::has_error() || internal.has_error();
}
bool reap_error(ErrorStack& errs) override
{
return BaseHandler::reap_error(errs) || internal.reap_error(errs);
}
virtual bool write(IHandler* output) const override
{
Converter<T>::to_shadow(*m_value, const_cast<shadow_type&>(shadow));
return internal.write(output);
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
return internal.generate_schema(output, alloc);
}
};
namespace helper
{
template <class T, bool no_conversion>
class DispatchHandler;
template <class T>
class DispatchHandler<T, true> : public ::staticjson::ObjectTypeHandler<T>
{
public:
explicit DispatchHandler(T* t) : ::staticjson::ObjectTypeHandler<T>(t) {}
};
template <class T>
class DispatchHandler<T, false> : public ::staticjson::ConversionHandler<T>
{
public:
explicit DispatchHandler(T* t) : ::staticjson::ConversionHandler<T>(t) {}
};
}
template <class T>
class Handler
: public helper::DispatchHandler<T, std::is_same<typename Converter<T>::shadow_type, T>::value>
{
public:
typedef helper::DispatchHandler<T, std::is_same<typename Converter<T>::shadow_type, T>::value>
base_type;
explicit Handler(T* t) : base_type(t) {}
};
}
================================================
FILE: include/staticjson/document.hpp
================================================
#pragma once
#include <staticjson/basic.hpp>
#include <rapidjson/document.h>
#include <vector>
namespace staticjson
{
class JSONHandler : public BaseHandler
{
protected:
static const int MAX_DEPTH = 32;
std::vector<Value> m_stack;
Value* m_value;
MemoryPoolAllocator* m_alloc;
private:
bool stack_push();
void stack_pop();
Value& stack_top();
bool postprocess();
bool set_corrupted_dom();
public:
explicit JSONHandler(Value* v, MemoryPoolAllocator* a);
std::string type_name() const override;
virtual bool Null() override;
virtual bool Bool(bool) override;
virtual bool Int(int) override;
virtual bool Uint(unsigned) override;
virtual bool Int64(std::int64_t) override;
virtual bool Uint64(std::uint64_t) override;
virtual bool Double(double) override;
virtual bool String(const char*, SizeType, bool) override;
virtual bool StartObject() override;
virtual bool Key(const char*, SizeType, bool) override;
virtual bool EndObject(SizeType) override;
virtual bool StartArray() override;
virtual bool EndArray(SizeType) override;
virtual bool write(IHandler* output) const override;
virtual void reset() override;
void reset(MemoryPoolAllocator* a);
void generate_schema(Value& output, MemoryPoolAllocator&) const override { output.SetObject(); }
};
template <>
class Handler<Document> : public JSONHandler
{
public:
explicit Handler(Document* h) : JSONHandler(h, &h->GetAllocator()) {}
virtual void reset() override
{
JSONHandler::reset(&(static_cast<Document*>(this->m_value)->GetAllocator()));
}
};
namespace nonpublic
{
bool write_value(const Value& v, BaseHandler* out, ParseStatus* status);
bool
read_value(Value* v, MemoryPoolAllocator* alloc, const BaseHandler* input, ParseStatus* status);
}
template <class T>
bool from_json_value(const Value& v, T* t, ParseStatus* status)
{
Handler<T> h(t);
return nonpublic::write_value(v, &h, status);
}
template <class T>
bool from_json_document(const Document& d,
T* t,
ParseStatus* status) // for consistency in API
{
return from_json_value(d, t, status);
}
template <class T>
bool to_json_value(Value* v, MemoryPoolAllocator* alloc, const T& t, ParseStatus* status)
{
Handler<T> h(const_cast<T*>(&t));
return nonpublic::read_value(v, alloc, &h, status);
}
template <class T>
bool to_json_document(Document* d, const T& t, ParseStatus* status)
{
return to_json_value(d, &d->GetAllocator(), t, status);
}
}
================================================
FILE: include/staticjson/enum.hpp
================================================
#pragma once
#include <staticjson/primitive_types.hpp>
#include <string>
#include <utility>
#include <vector>
namespace staticjson
{
template <class Enum, class Derived>
class EnumHandler : public BaseHandler
{
private:
Enum* m_value;
static const std::vector<std::pair<std::string, Enum>>& get_mapping()
{
return Derived::get_mapping();
};
public:
explicit EnumHandler(Enum* value) : m_value(value) {}
bool String(const char* str, SizeType sz, bool) override
{
const auto& mapping = get_mapping();
for (const std::pair<std::string, Enum>& pair : mapping)
{
if (pair.first.size() == sz && memcmp(pair.first.data(), str, sz) == 0)
{
*m_value = pair.second;
this->parsed = true;
return true;
}
}
the_error.reset(new error::InvalidEnumError(std::string(str, str + sz)));
return false;
}
bool write(IHandler* output) const override
{
const auto& mapping = get_mapping();
for (const std::pair<std::string, Enum>& pair : mapping)
{
if (*m_value == pair.second)
{
output->String(pair.first.data(), static_cast<SizeType>(pair.first.size()), false);
return true;
}
}
return false;
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("string"), alloc);
Value enumerations(rapidjson::kArrayType);
const auto& mapping = get_mapping();
for (const std::pair<std::string, Enum>& pair : mapping)
{
enumerations.PushBack(rapidjson::StringRef(pair.first.data(), pair.first.size()),
alloc);
}
output.AddMember(rapidjson::StringRef("enum"), enumerations, alloc);
}
};
}
#define STATICJSON_DECLARE_ENUM(type, ...) \
namespace staticjson \
{ \
template <> \
class Handler<type> : public EnumHandler<type, Handler<type>> \
{ \
public: \
explicit Handler(type* value) : EnumHandler<type, Handler<type>>(value) {} \
std::string type_name() const override { return #type; } \
static const std::vector<std::pair<std::string, type>>& get_mapping() \
{ \
static std::vector<std::pair<std::string, type>> mapping{__VA_ARGS__}; \
return mapping; \
} \
}; \
}
================================================
FILE: include/staticjson/error.hpp
================================================
#pragma once
#include <algorithm>
#include <cstddef>
#include <iterator>
#include <string>
#include <utility>
#include <vector>
namespace staticjson
{
std::string quote(const std::string& str);
class ErrorStack;
class ErrorBase;
namespace error
{
namespace internal
{
class error_stack_const_iterator;
}
using staticjson::ErrorBase;
using staticjson::ErrorStack;
}
class ErrorBase
{
protected:
explicit ErrorBase() : next(0) {}
private:
ErrorBase* next;
friend class ErrorStack;
friend class error::internal::error_stack_const_iterator;
public:
virtual int type() const = 0;
virtual bool is_intermediate() const { return false; }
virtual ~ErrorBase() {}
virtual std::string description() const = 0;
};
namespace error
{
typedef int error_type;
static const error_type SUCCESS = 0, OBJECT_MEMBER = 1, ARRAY_ELEMENT = 2, MISSING_REQUIRED = 3,
TYPE_MISMATCH = 4, NUMBER_OUT_OF_RANGE = 5, ARRAY_LENGTH_MISMATCH = 6,
UNKNOWN_FIELD = 7, DUPLICATE_KEYS = 8, CORRUPTED_DOM = 9,
TOO_DEEP_RECURSION = 10, INVALID_ENUM = 11, TOO_MANY_LEAVES = 12,
CUSTOM = -1;
class Success : public ErrorBase
{
public:
explicit Success() {}
std::string description() const;
error_type type() const { return SUCCESS; }
};
class IntermediateError : public ErrorBase
{
public:
bool is_intermediate() const { return true; }
};
class ObjectMemberError : public IntermediateError
{
private:
std::string m_member_name;
public:
explicit ObjectMemberError(std::string memberName) { m_member_name.swap(memberName); }
const std::string& member_name() const { return m_member_name; }
std::string description() const;
error_type type() const { return OBJECT_MEMBER; }
};
class ArrayElementError : public IntermediateError
{
private:
std::size_t m_index;
public:
explicit ArrayElementError(std::size_t idx) : m_index(idx) {}
std::size_t index() const { return m_index; }
std::string description() const;
error_type type() const { return ARRAY_ELEMENT; }
};
class RequiredFieldMissingError : public ErrorBase
{
private:
std::vector<std::string> m_missing_members;
public:
explicit RequiredFieldMissingError() {}
std::vector<std::string>& missing_members() { return m_missing_members; };
const std::vector<std::string>& missing_members() const { return m_missing_members; }
std::string description() const;
error_type type() const { return MISSING_REQUIRED; }
};
class TypeMismatchError : public ErrorBase
{
private:
std::string m_expected_type;
std::string m_actual_type;
public:
explicit TypeMismatchError(std::string expectedType, std::string actualType)
{
m_expected_type.swap(expectedType);
m_actual_type.swap(actualType);
}
const std::string& expected_type() const { return m_expected_type; }
const std::string& actual_type() const { return m_actual_type; }
std::string description() const;
error_type type() const { return TYPE_MISMATCH; }
};
class RecursionTooDeepError : public ErrorBase
{
std::string description() const override;
error_type type() const override { return TOO_DEEP_RECURSION; }
};
class TooManyLeavesError : public ErrorBase
{
std::string description() const override;
error_type type() const override { return TOO_MANY_LEAVES; }
};
class NumberOutOfRangeError : public ErrorBase
{
std::string m_expected_type;
std::string m_actual_type;
public:
explicit NumberOutOfRangeError(std::string expectedType, std::string actualType)
{
m_expected_type.swap(expectedType);
m_actual_type.swap(actualType);
}
const std::string& expected_type() const { return m_expected_type; }
const std::string& actual_type() const { return m_actual_type; }
std::string description() const;
error_type type() const { return NUMBER_OUT_OF_RANGE; }
};
class DuplicateKeyError : public ErrorBase
{
private:
std::string key_name;
public:
explicit DuplicateKeyError(std::string name) { key_name.swap(name); }
const std::string& key() const { return key_name; }
error_type type() const { return DUPLICATE_KEYS; }
std::string description() const;
};
class UnknownFieldError : public ErrorBase
{
private:
std::string m_name;
public:
explicit UnknownFieldError(const char* name, std::size_t length) : m_name(name, length) {}
const std::string& field_name() const { return m_name; }
error_type type() const { return UNKNOWN_FIELD; }
std::string description() const;
};
class CorruptedDOMError : public ErrorBase
{
public:
std::string description() const;
error_type type() const { return CORRUPTED_DOM; }
};
class ArrayLengthMismatchError : public ErrorBase
{
public:
std::string description() const;
error_type type() const { return ARRAY_LENGTH_MISMATCH; }
};
class InvalidEnumError : public ErrorBase
{
private:
std::string m_name;
public:
explicit InvalidEnumError(std::string name) { m_name.swap(name); }
std::string description() const;
error_type type() const { return INVALID_ENUM; }
};
class CustomError : public ErrorBase
{
private:
std::string m_message;
public:
explicit CustomError(std::string message) { m_message.swap(message); }
std::string description() const;
error_type type() const { return CUSTOM; }
};
namespace internal
{
class error_stack_const_iterator
{
private:
const ErrorBase* e;
public:
using iterator_category = std::forward_iterator_tag;
using value_type = const ErrorBase;
using difference_type = ptrdiff_t;
using pointer = const ErrorBase*;
using reference = const ErrorBase&;
public:
explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
reference operator*() const { return *e; }
pointer operator->() const { return e; }
error_stack_const_iterator& operator++()
{
e = e->next;
return *this;
}
bool operator==(error_stack_const_iterator that) const { return e == that.e; }
bool operator!=(error_stack_const_iterator that) const { return e != that.e; }
};
}
}
class ErrorStack
{
private:
ErrorBase* head;
std::size_t m_size;
ErrorStack(const ErrorStack&);
ErrorStack& operator=(const ErrorStack&);
public:
typedef error::internal::error_stack_const_iterator const_iterator;
explicit ErrorStack() : head(0), m_size(0) {}
const_iterator begin() const { return const_iterator(head); }
const_iterator end() const { return const_iterator(0); }
// This will take the ownership of e
// Requires it to be dynamically allocated
void push(ErrorBase* e)
{
if (e)
{
e->next = head;
head = e;
++m_size;
}
}
// The caller will take the responsibility of deleting the returned pointer
// Returns NULL when empty
ErrorBase* pop()
{
if (head)
{
ErrorBase* result = head;
head = head->next;
--m_size;
return result;
}
return 0;
}
bool empty() const { return head == 0; }
explicit operator bool() const { return !empty(); }
bool operator!() const { return empty(); }
std::size_t size() const { return m_size; }
~ErrorStack()
{
while (head)
{
ErrorBase* next = head->next;
delete head;
head = next;
}
}
void swap(ErrorStack& other) noexcept
{
std::swap(head, other.head);
std::swap(m_size, other.m_size);
}
ErrorStack(ErrorStack&& other) : head(other.head), m_size(other.m_size)
{
other.head = 0;
other.m_size = 0;
}
ErrorStack& operator==(ErrorStack&& other)
{
swap(other);
return *this;
}
};
// For argument dependent lookup
inline void swap(ErrorStack& s1, ErrorStack& s2) { s1.swap(s2); }
class ParseStatus
{
private:
ErrorStack m_stack;
std::size_t m_offset;
int m_code;
public:
explicit ParseStatus() : m_stack(), m_offset(), m_code() {}
void set_result(int err, std::size_t off)
{
m_code = err;
m_offset = off;
}
int error_code() const { return m_code; }
std::size_t offset() const { return m_offset; }
std::string short_description() const;
ErrorStack& error_stack() { return m_stack; }
const ErrorStack& error_stack() const { return m_stack; }
typedef ErrorStack::const_iterator const_iterator;
const_iterator begin() const { return m_stack.begin(); }
const_iterator end() const { return m_stack.end(); }
bool has_error() const { return m_code != 0 || !m_stack.empty(); }
std::string description() const;
void swap(ParseStatus& other) noexcept
{
std::swap(m_code, other.m_code);
std::swap(m_offset, other.m_offset);
m_stack.swap(other.m_stack);
}
bool operator!() const { return has_error(); }
explicit operator bool() const { return !has_error(); }
ParseStatus(ParseStatus&& other) noexcept : m_stack(), m_offset(), m_code() { swap(other); }
ParseStatus& operator==(ParseStatus&& other) noexcept
{
swap(other);
return *this;
}
};
// For argument dependent lookup
inline void swap(ParseStatus& r1, ParseStatus& r2) { r1.swap(r2); }
}
================================================
FILE: include/staticjson/forward_declarations.hpp
================================================
#pragma once
namespace staticjson
{
typedef unsigned int SizeType;
class IHandler;
class BaseHandler;
class ObjectHandler;
template <class T>
class Handler;
}
================================================
FILE: include/staticjson/io.hpp
================================================
#pragma once
#include <staticjson/basic.hpp>
#include <cstdio>
#include <string>
namespace staticjson
{
namespace nonpublic
{
bool parse_json_string(const char* str, BaseHandler* handler, ParseStatus* status);
bool parse_json_file(std::FILE* fp, BaseHandler* handler, ParseStatus* status);
std::string serialize_json_string(const BaseHandler* handler);
bool serialize_json_file(std::FILE* fp, const BaseHandler* handler);
std::string serialize_pretty_json_string(const BaseHandler* handler);
bool serialize_pretty_json_file(std::FILE* fp, const BaseHandler* handler);
struct FileGuard : private NonMobile
{
std::FILE* fp;
explicit FileGuard(std::FILE* fp) : fp(fp) {}
~FileGuard()
{
if (fp)
std::fclose(fp);
}
};
}
template <class T>
inline bool from_json_string(const char* str, T* value, ParseStatus* status)
{
Handler<T> h(value);
return nonpublic::parse_json_string(str, &h, status);
}
template <class T>
inline bool from_json_file(std::FILE* fp, T* value, ParseStatus* status)
{
Handler<T> h(value);
return nonpublic::parse_json_file(fp, &h, status);
}
template <class T>
inline bool from_json_file(const char* filename, T* value, ParseStatus* status)
{
nonpublic::FileGuard fg(std::fopen(filename, "r"));
return from_json_file(fg.fp, value, status);
}
template <class T>
inline bool from_json_file(const std::string& filename, T* value, ParseStatus* status)
{
return from_json_file(filename.c_str(), value, status);
}
template <class T>
inline std::string to_json_string(const T& value)
{
Handler<T> h(const_cast<T*>(&value));
return nonpublic::serialize_json_string(&h);
}
template <class T>
inline bool to_json_file(std::FILE* fp, const T& value)
{
Handler<T> h(const_cast<T*>(&value));
return nonpublic::serialize_json_file(fp, &h);
}
template <class T>
inline bool to_json_file(const char* filename, const T& value)
{
nonpublic::FileGuard fg(std::fopen(filename, "wb"));
return to_json_file(fg.fp, value);
}
template <class T>
inline bool to_json_file(const std::string& filename, const T& value)
{
return to_json_file(filename.c_str(), value);
}
template <class T>
inline std::string to_pretty_json_string(const T& value)
{
Handler<T> h(const_cast<T*>(&value));
return nonpublic::serialize_pretty_json_string(&h);
}
template <class T>
inline bool to_pretty_json_file(std::FILE* fp, const T& value)
{
Handler<T> h(const_cast<T*>(&value));
return nonpublic::serialize_pretty_json_file(fp, &h);
}
template <class T>
inline bool to_pretty_json_file(const char* filename, const T& value)
{
nonpublic::FileGuard fg(std::fopen(filename, "wb"));
return to_pretty_json_file(fg.fp, value);
}
template <class T>
inline bool to_pretty_json_file(const std::string& filename, const T& value)
{
return to_pretty_json_file(filename.c_str(), value);
}
template <class T>
inline Document export_json_schema(T* value, Document::AllocatorType* allocator = nullptr)
{
Handler<T> h(value);
Document d;
h.generate_schema(d, allocator ? *allocator : d.GetAllocator());
return d;
}
}
================================================
FILE: include/staticjson/optional_support.hpp
================================================
#pragma once
#include "stl_types.hpp"
#ifdef __has_include
#if __has_include(<optional>)
#include <optional>
namespace staticjson
{
template <typename T>
using optional = std::optional<T>;
using std::nullopt;
}
#elif __has_include(<experimental/optional>)
#include <experimental/optional>
namespace staticjson
{
template <typename T>
using optional = std::experimental::optional<T>;
using std::experimental::nullopt;
}
#else
#error "Missing <optional>"
#endif
#else
#error "Missing <optional>"
#endif
namespace staticjson
{
template <class T>
class Handler<optional<T>> : public BaseHandler
{
public:
using ElementType = T;
protected:
mutable optional<T>* m_value;
mutable optional<Handler<ElementType>> internal_handler;
int depth = 0;
public:
explicit Handler(optional<T>* value) : m_value(value) {}
protected:
void initialize()
{
if (!internal_handler)
{
m_value->emplace();
internal_handler.emplace(&(**m_value));
}
}
void reset() override
{
depth = 0;
internal_handler = nullopt;
*m_value = nullopt;
}
bool postcheck(bool success)
{
if (success)
this->parsed = internal_handler->is_parsed();
return success;
}
public:
bool Null() override
{
if (depth == 0)
{
*m_value = nullopt;
this->parsed = true;
return true;
}
else
{
initialize();
return postcheck(internal_handler->Null());
}
}
bool write(IHandler* out) const override
{
if (!m_value || !(*m_value))
{
return out->Null();
}
if (!internal_handler)
{
internal_handler.emplace(&(**m_value));
}
return internal_handler->write(out);
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
const_cast<Handler<optional<T>>*>(this)->initialize();
output.SetObject();
Value anyOf(rapidjson::kArrayType);
Value nullDescriptor(rapidjson::kObjectType);
nullDescriptor.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("null"), alloc);
Value descriptor;
internal_handler->generate_schema(descriptor, alloc);
anyOf.PushBack(nullDescriptor, alloc);
anyOf.PushBack(descriptor, alloc);
output.AddMember(rapidjson::StringRef("anyOf"), anyOf, alloc);
}
bool Bool(bool b) override
{
initialize();
return postcheck(internal_handler->Bool(b));
}
bool Int(int i) override
{
initialize();
return postcheck(internal_handler->Int(i));
}
bool Uint(unsigned i) override
{
initialize();
return postcheck(internal_handler->Uint(i));
}
bool Int64(std::int64_t i) override
{
initialize();
return postcheck(internal_handler->Int64(i));
}
bool Uint64(std::uint64_t i) override
{
initialize();
return postcheck(internal_handler->Uint64(i));
}
bool Double(double i) override
{
initialize();
return postcheck(internal_handler->Double(i));
}
bool String(const char* str, SizeType len, bool copy) override
{
initialize();
return postcheck(internal_handler->String(str, len, copy));
}
bool Key(const char* str, SizeType len, bool copy) override
{
initialize();
return postcheck(internal_handler->Key(str, len, copy));
}
bool StartObject() override
{
initialize();
++depth;
return internal_handler->StartObject();
}
bool EndObject(SizeType len) override
{
initialize();
--depth;
return postcheck(internal_handler->EndObject(len));
}
bool StartArray() override
{
initialize();
++depth;
return postcheck(internal_handler->StartArray());
}
bool EndArray(SizeType len) override
{
initialize();
--depth;
return postcheck(internal_handler->EndArray(len));
}
bool has_error() const override { return internal_handler && internal_handler->has_error(); }
bool reap_error(ErrorStack& stk) override
{
return internal_handler && internal_handler->reap_error(stk);
}
std::string type_name() const override
{
if (this->internal_handler)
{
return "std::optional<" + this->internal_handler->type_name() + ">";
}
return "std::optional";
}
};
}
================================================
FILE: include/staticjson/primitive_types.hpp
================================================
#pragma once
#include <staticjson/basic.hpp>
#include <limits>
#include <string>
#include <type_traits>
namespace staticjson
{
template <class IntType>
class IntegerHandler : public BaseHandler
{
static_assert(std::is_arithmetic<IntType>::value, "Only arithmetic types are allowed");
protected:
IntType* m_value;
template <class AnotherIntType>
static constexpr typename std::enable_if<std::is_integral<AnotherIntType>::value, bool>::type
is_out_of_range(AnotherIntType a)
{
typedef typename std::common_type<IntType, AnotherIntType>::type CommonType;
typedef typename std::numeric_limits<IntType> this_limits;
typedef typename std::numeric_limits<AnotherIntType> that_limits;
// The extra logic related to this_limits::min/max allows the compiler to
// short circuit this check at compile time. For instance, a `uint32_t`
// will NEVER be out of range for an `int64_t`
return ((this_limits::is_signed == that_limits::is_signed)
? ((CommonType(this_limits::min()) > CommonType(a)
|| CommonType(this_limits::max()) < CommonType(a)))
: (this_limits::is_signed)
? (CommonType(this_limits::max()) < CommonType(a))
: (a < 0 || CommonType(a) > CommonType(this_limits::max())));
}
template <class FloatType>
static constexpr typename std::enable_if<std::is_floating_point<FloatType>::value, bool>::type
is_out_of_range(FloatType f)
{
return static_cast<FloatType>(static_cast<IntType>(f)) != f;
}
template <class ReceiveNumType>
bool receive(ReceiveNumType r, const char* actual_type)
{
if (is_out_of_range(r))
return set_out_of_range(actual_type);
*m_value = static_cast<IntType>(r);
this->parsed = true;
return true;
}
public:
explicit IntegerHandler(IntType* value) : m_value(value) {}
bool Int(int i) override { return receive(i, "int"); }
bool Uint(unsigned i) override { return receive(i, "unsigned int"); }
bool Int64(std::int64_t i) override { return receive(i, "std::int64_t"); }
bool Uint64(std::uint64_t i) override { return receive(i, "std::uint64_t"); }
bool Double(double d) override { return receive(d, "double"); }
bool write(IHandler* output) const override
{
if (std::numeric_limits<IntType>::is_signed)
{
return output->Int64(*m_value);
}
else
{
return output->Uint64(*m_value);
}
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("integer"), alloc);
Value minimum, maximum;
if (std::numeric_limits<IntType>::is_signed)
{
minimum.SetInt64(std::numeric_limits<IntType>::min());
maximum.SetInt64(std::numeric_limits<IntType>::max());
}
else
{
minimum.SetUint64(std::numeric_limits<IntType>::min());
maximum.SetUint64(std::numeric_limits<IntType>::max());
}
output.AddMember(rapidjson::StringRef("minimum"), minimum, alloc);
output.AddMember(rapidjson::StringRef("maximum"), maximum, alloc);
}
};
template <>
class Handler<std::nullptr_t> : public BaseHandler
{
public:
explicit Handler(std::nullptr_t*) {}
bool Null() override
{
this->parsed = true;
return true;
}
std::string type_name() const override { return "null"; }
bool write(IHandler* output) const override { return output->Null(); }
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("null"), alloc);
}
};
template <>
class Handler<bool> : public BaseHandler
{
private:
bool* m_value;
public:
explicit Handler(bool* value) : m_value(value) {}
bool Bool(bool v) override
{
*m_value = v;
this->parsed = true;
return true;
}
std::string type_name() const override { return "bool"; }
bool write(IHandler* output) const override { return output->Bool(*m_value); }
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("boolean"), alloc);
}
};
template <>
class Handler<int> : public IntegerHandler<int>
{
public:
explicit Handler(int* i) : IntegerHandler<int>(i) {}
std::string type_name() const override { return "int"; }
bool write(IHandler* output) const override { return output->Int(*m_value); }
};
template <>
class Handler<unsigned int> : public IntegerHandler<unsigned int>
{
public:
explicit Handler(unsigned* i) : IntegerHandler<unsigned int>(i) {}
std::string type_name() const override { return "unsigned int"; }
bool write(IHandler* output) const override { return output->Uint(*m_value); }
};
template <>
class Handler<long> : public IntegerHandler<long>
{
public:
explicit Handler(long* i) : IntegerHandler<long>(i) {}
std::string type_name() const override { return "long"; }
};
template <>
class Handler<unsigned long> : public IntegerHandler<unsigned long>
{
public:
explicit Handler(unsigned long* i) : IntegerHandler<unsigned long>(i) {}
std::string type_name() const override { return "unsigned long"; }
};
template <>
class Handler<long long> : public IntegerHandler<long long>
{
public:
explicit Handler(long long* i) : IntegerHandler<long long>(i) {}
std::string type_name() const override { return "long long"; }
};
template <>
class Handler<unsigned long long> : public IntegerHandler<unsigned long long>
{
public:
explicit Handler(unsigned long long* i) : IntegerHandler<unsigned long long>(i) {}
std::string type_name() const override { return "unsigned long long"; }
};
// char is an alias for bool to work around the stupid `std::vector<bool>`
template <>
class Handler<char> : public BaseHandler
{
private:
char* m_value;
public:
explicit Handler(char* i) : m_value(i) {}
std::string type_name() const override { return "bool"; }
bool Bool(bool v) override
{
*this->m_value = v;
this->parsed = true;
return true;
}
bool write(IHandler* out) const override { return out->Bool(*m_value != 0); }
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("boolean"), alloc);
}
};
template <>
class Handler<double> : public BaseHandler
{
private:
double* m_value;
public:
explicit Handler(double* v) : m_value(v) {}
bool Int(int i) override
{
*m_value = i;
this->parsed = true;
return true;
}
bool Uint(unsigned i) override
{
*m_value = i;
this->parsed = true;
return true;
}
bool Int64(std::int64_t i) override
{
*m_value = static_cast<double>(i);
if (static_cast<decltype(i)>(*m_value) != i)
return set_out_of_range("std::int64_t");
this->parsed = true;
return true;
}
bool Uint64(std::uint64_t i) override
{
*m_value = static_cast<double>(i);
if (static_cast<decltype(i)>(*m_value) != i)
return set_out_of_range("std::uint64_t");
this->parsed = true;
return true;
}
bool Double(double d) override
{
*m_value = d;
this->parsed = true;
return true;
}
std::string type_name() const override { return "double"; }
bool write(IHandler* out) const override { return out->Double(*m_value); }
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("number"), alloc);
}
};
template <>
class Handler<float> : public BaseHandler
{
private:
float* m_value;
public:
explicit Handler(float* v) : m_value(v) {}
bool Int(int i) override
{
*m_value = static_cast<float>(i);
if (static_cast<decltype(i)>(*m_value) != i)
return set_out_of_range("int");
this->parsed = true;
return true;
}
bool Uint(unsigned i) override
{
*m_value = static_cast<float>(i);
if (static_cast<decltype(i)>(*m_value) != i)
return set_out_of_range("unsigned int");
this->parsed = true;
return true;
}
bool Int64(std::int64_t i) override
{
*m_value = static_cast<float>(i);
if (static_cast<decltype(i)>(*m_value) != i)
return set_out_of_range("std::int64_t");
this->parsed = true;
return true;
}
bool Uint64(std::uint64_t i) override
{
*m_value = static_cast<float>(i);
if (static_cast<decltype(i)>(*m_value) != i)
return set_out_of_range("std::uint64_t");
this->parsed = true;
return true;
}
bool Double(double d) override
{
*m_value = static_cast<float>(d);
this->parsed = true;
return true;
}
std::string type_name() const override { return "float"; }
bool write(IHandler* out) const override { return out->Double(*m_value); }
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("number"), alloc);
}
};
template <>
class Handler<std::string> : public BaseHandler
{
private:
std::string* m_value;
public:
explicit Handler(std::string* v) : m_value(v) {}
bool String(const char* str, SizeType length, bool) override
{
m_value->assign(str, length);
this->parsed = true;
return true;
}
std::string type_name() const override { return "string"; }
bool write(IHandler* out) const override
{
return out->String(m_value->data(), SizeType(m_value->size()), true);
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("string"), alloc);
}
};
}
================================================
FILE: include/staticjson/staticjson.hpp
================================================
#pragma once
#include <staticjson/basic.hpp>
#include <staticjson/document.hpp>
#include <staticjson/enum.hpp>
#include <staticjson/io.hpp>
#include <staticjson/primitive_types.hpp>
#include <staticjson/stl_types.hpp>
================================================
FILE: include/staticjson/stl_types.hpp
================================================
#pragma once
#include <staticjson/basic.hpp>
#include <array>
#include <deque>
#include <list>
#include <map>
#include <memory>
#include <tuple>
#include <unordered_map>
#include <vector>
namespace staticjson
{
template <class ArrayType>
class ArrayHandler : public BaseHandler
{
public:
typedef typename ArrayType::value_type ElementType;
protected:
ElementType element;
Handler<ElementType> internal;
ArrayType* m_value;
int depth = 0;
protected:
void set_element_error() { the_error.reset(new error::ArrayElementError(m_value->size())); }
bool precheck(const char* type)
{
if (depth <= 0)
{
the_error.reset(new error::TypeMismatchError(type_name(), type));
return false;
}
return true;
}
bool postcheck(bool success)
{
if (!success)
{
set_element_error();
return false;
}
if (internal.is_parsed())
{
m_value->emplace_back(std::move(element));
element = ElementType();
internal.prepare_for_reuse();
}
return true;
}
void reset() override
{
element = ElementType();
internal.prepare_for_reuse();
depth = 0;
}
public:
explicit ArrayHandler(ArrayType* value) : element(), internal(&element), m_value(value) {}
bool Null() override { return precheck("null") && postcheck(internal.Null()); }
bool Bool(bool b) override { return precheck("bool") && postcheck(internal.Bool(b)); }
bool Int(int i) override { return precheck("int") && postcheck(internal.Int(i)); }
bool Uint(unsigned i) override { return precheck("unsigned") && postcheck(internal.Uint(i)); }
bool Int64(std::int64_t i) override
{
return precheck("int64_t") && postcheck(internal.Int64(i));
}
bool Uint64(std::uint64_t i) override
{
return precheck("uint64_t") && postcheck(internal.Uint64(i));
}
bool Double(double d) override { return precheck("double") && postcheck(internal.Double(d)); }
bool String(const char* str, SizeType length, bool copy) override
{
return precheck("string") && postcheck(internal.String(str, length, copy));
}
bool Key(const char* str, SizeType length, bool copy) override
{
return precheck("object") && postcheck(internal.Key(str, length, copy));
}
bool StartObject() override { return precheck("object") && postcheck(internal.StartObject()); }
bool EndObject(SizeType length) override
{
return precheck("object") && postcheck(internal.EndObject(length));
}
bool StartArray() override
{
++depth;
if (depth > 1)
return postcheck(internal.StartArray());
else
m_value->clear();
return true;
}
bool EndArray(SizeType length) override
{
--depth;
// When depth >= 1, this event should be forwarded to the element
if (depth > 0)
return postcheck(internal.EndArray(length));
this->parsed = true;
return true;
}
bool reap_error(ErrorStack& stk) override
{
if (!the_error)
return false;
stk.push(the_error.release());
internal.reap_error(stk);
return true;
}
bool write(IHandler* output) const override
{
if (!output->StartArray())
return false;
for (auto&& e : *m_value)
{
Handler<ElementType> h(&e);
if (!h.write(output))
return false;
}
return output->EndArray(static_cast<staticjson::SizeType>(m_value->size()));
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("array"), alloc);
Value items;
internal.generate_schema(items, alloc);
output.AddMember(rapidjson::StringRef("items"), items, alloc);
}
const Handler<ElementType>& get_internal_handler() const noexcept { return internal; }
};
template <class T>
class Handler<std::vector<T>> : public ArrayHandler<std::vector<T>>
{
public:
explicit Handler(std::vector<T>* value) : ArrayHandler<std::vector<T>>(value) {}
std::string type_name() const override
{
return "std::vector<" + this->internal.type_name() + ">";
}
};
template <class T>
class Handler<std::deque<T>> : public ArrayHandler<std::deque<T>>
{
public:
explicit Handler(std::deque<T>* value) : ArrayHandler<std::deque<T>>(value) {}
std::string type_name() const override
{
return "std::deque<" + this->internal.type_name() + ">";
}
};
template <class T>
class Handler<std::list<T>> : public ArrayHandler<std::list<T>>
{
public:
explicit Handler(std::list<T>* value) : ArrayHandler<std::list<T>>(value) {}
std::string type_name() const override
{
return "std::list<" + this->internal.type_name() + ">";
}
};
template <class T, size_t N>
class Handler<std::array<T, N>> : public BaseHandler
{
protected:
T element;
Handler<T> internal;
std::array<T, N>* m_value;
size_t count = 0;
int depth = 0;
protected:
void set_element_error() { the_error.reset(new error::ArrayElementError(count)); }
void set_length_error() { the_error.reset(new error::ArrayLengthMismatchError()); }
bool precheck(const char* type)
{
if (depth <= 0)
{
the_error.reset(new error::TypeMismatchError(type_name(), type));
return false;
}
return true;
}
bool postcheck(bool success)
{
if (!success)
{
set_element_error();
return false;
}
if (internal.is_parsed())
{
if (count >= N)
{
set_length_error();
return false;
}
(*m_value)[count] = std::move(element);
++count;
element = T();
internal.prepare_for_reuse();
}
return true;
}
void reset() override
{
element = T();
internal.prepare_for_reuse();
depth = 0;
count = 0;
}
public:
explicit Handler(std::array<T, N>* value) : element(), internal(&element), m_value(value) {}
bool Null() override { return precheck("null") && postcheck(internal.Null()); }
bool Bool(bool b) override { return precheck("bool") && postcheck(internal.Bool(b)); }
bool Int(int i) override { return precheck("int") && postcheck(internal.Int(i)); }
bool Uint(unsigned i) override { return precheck("unsigned") && postcheck(internal.Uint(i)); }
bool Int64(std::int64_t i) override
{
return precheck("int64_t") && postcheck(internal.Int64(i));
}
bool Uint64(std::uint64_t i) override
{
return precheck("uint64_t") && postcheck(internal.Uint64(i));
}
bool Double(double d) override { return precheck("double") && postcheck(internal.Double(d)); }
bool String(const char* str, SizeType length, bool copy) override
{
return precheck("string") && postcheck(internal.String(str, length, copy));
}
bool Key(const char* str, SizeType length, bool copy) override
{
return precheck("object") && postcheck(internal.Key(str, length, copy));
}
bool StartObject() override { return precheck("object") && postcheck(internal.StartObject()); }
bool EndObject(SizeType length) override
{
return precheck("object") && postcheck(internal.EndObject(length));
}
bool StartArray() override
{
++depth;
if (depth > 1)
return postcheck(internal.StartArray());
return true;
}
bool EndArray(SizeType length) override
{
--depth;
// When depth >= 1, this event should be forwarded to the element
if (depth > 0)
return postcheck(internal.EndArray(length));
if (count != N)
{
set_length_error();
return false;
}
this->parsed = true;
return true;
}
bool reap_error(ErrorStack& stk) override
{
if (!the_error)
return false;
stk.push(the_error.release());
internal.reap_error(stk);
return true;
}
bool write(IHandler* output) const override
{
if (!output->StartArray())
return false;
for (auto&& e : *m_value)
{
Handler<T> h(&e);
if (!h.write(output))
return false;
}
return output->EndArray(static_cast<staticjson::SizeType>(m_value->size()));
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("array"), alloc);
Value items;
internal.generate_schema(items, alloc);
output.AddMember(rapidjson::StringRef("items"), items, alloc);
output.AddMember(rapidjson::StringRef("minItems"), static_cast<uint64_t>(N), alloc);
output.AddMember(rapidjson::StringRef("maxItems"), static_cast<uint64_t>(N), alloc);
}
std::string type_name() const override
{
return "std::array<" + internal.type_name() + ", " + std::to_string(N) + ">";
}
};
template <class PointerType>
class PointerHandler : public BaseHandler
{
public:
typedef typename std::pointer_traits<PointerType>::element_type ElementType;
protected:
mutable PointerType* m_value;
mutable std::unique_ptr<Handler<ElementType>> internal_handler;
int depth = 0;
protected:
explicit PointerHandler(PointerType* value) : m_value(value) {}
void initialize()
{
if (!internal_handler)
{
m_value->reset(new ElementType());
internal_handler.reset(new Handler<ElementType>(m_value->get()));
}
}
void reset() override
{
depth = 0;
internal_handler.reset();
m_value->reset();
}
bool postcheck(bool success)
{
if (success)
this->parsed = internal_handler->is_parsed();
return success;
}
public:
bool Null() override
{
if (depth == 0)
{
m_value->reset();
this->parsed = true;
return true;
}
else
{
initialize();
return postcheck(internal_handler->Null());
}
}
bool write(IHandler* out) const override
{
if (!m_value || !m_value->get())
{
return out->Null();
}
if (!internal_handler)
{
internal_handler.reset(new Handler<ElementType>(m_value->get()));
}
return internal_handler->write(out);
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
const_cast<PointerHandler<PointerType>*>(this)->initialize();
output.SetObject();
Value anyOf(rapidjson::kArrayType);
Value nullDescriptor(rapidjson::kObjectType);
nullDescriptor.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("null"), alloc);
Value descriptor;
internal_handler->generate_schema(descriptor, alloc);
anyOf.PushBack(nullDescriptor, alloc);
anyOf.PushBack(descriptor, alloc);
output.AddMember(rapidjson::StringRef("anyOf"), anyOf, alloc);
}
bool Bool(bool b) override
{
initialize();
return postcheck(internal_handler->Bool(b));
}
bool Int(int i) override
{
initialize();
return postcheck(internal_handler->Int(i));
}
bool Uint(unsigned i) override
{
initialize();
return postcheck(internal_handler->Uint(i));
}
bool Int64(std::int64_t i) override
{
initialize();
return postcheck(internal_handler->Int64(i));
}
bool Uint64(std::uint64_t i) override
{
initialize();
return postcheck(internal_handler->Uint64(i));
}
bool Double(double i) override
{
initialize();
return postcheck(internal_handler->Double(i));
}
bool String(const char* str, SizeType len, bool copy) override
{
initialize();
return postcheck(internal_handler->String(str, len, copy));
}
bool Key(const char* str, SizeType len, bool copy) override
{
initialize();
return postcheck(internal_handler->Key(str, len, copy));
}
bool StartObject() override
{
initialize();
++depth;
return internal_handler->StartObject();
}
bool EndObject(SizeType len) override
{
initialize();
--depth;
return postcheck(internal_handler->EndObject(len));
}
bool StartArray() override
{
initialize();
++depth;
return postcheck(internal_handler->StartArray());
}
bool EndArray(SizeType len) override
{
initialize();
--depth;
return postcheck(internal_handler->EndArray(len));
}
bool has_error() const override { return internal_handler && internal_handler->has_error(); }
bool reap_error(ErrorStack& stk) override
{
return internal_handler && internal_handler->reap_error(stk);
}
};
template <class T, class Deleter>
class Handler<std::unique_ptr<T, Deleter>> : public PointerHandler<std::unique_ptr<T, Deleter>>
{
public:
explicit Handler(std::unique_ptr<T, Deleter>* value)
: PointerHandler<std::unique_ptr<T, Deleter>>(value)
{
}
std::string type_name() const override
{
if (this->internal_handler)
{
return "std::unique_ptr<" + this->internal_handler->type_name() + ">";
}
return "std::unique_ptr";
}
};
template <class T>
class Handler<std::shared_ptr<T>> : public PointerHandler<std::shared_ptr<T>>
{
public:
explicit Handler(std::shared_ptr<T>* value) : PointerHandler<std::shared_ptr<T>>(value) {}
std::string type_name() const override
{
if (this->internal_handler)
{
return "std::shared_ptr<" + this->internal_handler->type_name() + ">";
}
return "std::shared_ptr";
}
};
template <class MapType>
class MapHandler : public BaseHandler
{
protected:
typedef typename MapType::mapped_type ElementType;
protected:
ElementType element;
Handler<ElementType> internal_handler;
MapType* m_value;
std::string current_key;
int depth = 0;
protected:
void reset() override
{
element = ElementType();
current_key.clear();
internal_handler.prepare_for_reuse();
depth = 0;
}
bool precheck(const char* type)
{
if (depth <= 0)
{
set_type_mismatch(type);
return false;
}
return true;
}
bool postcheck(bool success)
{
if (!success)
{
the_error.reset(new error::ObjectMemberError(current_key));
}
else
{
if (internal_handler.is_parsed())
{
m_value->emplace(std::move(current_key), std::move(element));
element = ElementType();
internal_handler.prepare_for_reuse();
}
}
return success;
}
public:
explicit MapHandler(MapType* value) : element(), internal_handler(&element), m_value(value) {}
bool Null() override { return precheck("null") && postcheck(internal_handler.Null()); }
bool Bool(bool b) override { return precheck("bool") && postcheck(internal_handler.Bool(b)); }
bool Int(int i) override { return precheck("int") && postcheck(internal_handler.Int(i)); }
bool Uint(unsigned i) override
{
return precheck("unsigned") && postcheck(internal_handler.Uint(i));
}
bool Int64(std::int64_t i) override
{
return precheck("int64_t") && postcheck(internal_handler.Int64(i));
}
bool Uint64(std::uint64_t i) override
{
return precheck("uint64_t") && postcheck(internal_handler.Uint64(i));
}
bool Double(double d) override
{
return precheck("double") && postcheck(internal_handler.Double(d));
}
bool String(const char* str, SizeType length, bool copy) override
{
return precheck("string") && postcheck(internal_handler.String(str, length, copy));
}
bool Key(const char* str, SizeType length, bool copy) override
{
if (depth > 1)
return postcheck(internal_handler.Key(str, length, copy));
current_key.assign(str, length);
return true;
}
bool StartArray() override
{
return precheck("array") && postcheck(internal_handler.StartArray());
}
bool EndArray(SizeType length) override
{
return precheck("array") && postcheck(internal_handler.EndArray(length));
}
bool StartObject() override
{
++depth;
if (depth > 1)
return postcheck(internal_handler.StartObject());
else
m_value->clear();
return true;
}
bool EndObject(SizeType length) override
{
--depth;
if (depth > 0)
return postcheck(internal_handler.EndObject(length));
this->parsed = true;
return true;
}
bool reap_error(ErrorStack& errs) override
{
if (!this->the_error)
return false;
errs.push(this->the_error.release());
internal_handler.reap_error(errs);
return true;
}
bool write(IHandler* out) const override
{
if (!out->StartObject())
return false;
for (auto&& pair : *m_value)
{
if (!out->Key(pair.first.data(), static_cast<SizeType>(pair.first.size()), true))
return false;
Handler<ElementType> h(&pair.second);
if (!h.write(out))
return false;
}
return out->EndObject(static_cast<SizeType>(m_value->size()));
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
Value internal_schema;
internal_handler.generate_schema(internal_schema, alloc);
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("object"), alloc);
Value empty_obj(rapidjson::kObjectType);
output.AddMember(rapidjson::StringRef("properties"), empty_obj, alloc);
output.AddMember(rapidjson::StringRef("additionalProperties"), internal_schema, alloc);
}
};
template <class T, class Hash, class Equal>
class Handler<std::unordered_map<std::string, T, Hash, Equal>>
: public MapHandler<std::unordered_map<std::string, T, Hash, Equal>>
{
public:
explicit Handler(std::unordered_map<std::string, T, Hash, Equal>* value)
: MapHandler<std::unordered_map<std::string, T, Hash, Equal>>(value)
{
}
std::string type_name() const override
{
return "std::unordered_map<std::string, " + this->internal_handler.type_name() + ">";
}
};
template <class T, class Hash, class Equal>
class Handler<std::map<std::string, T, Hash, Equal>>
: public MapHandler<std::map<std::string, T, Hash, Equal>>
{
public:
explicit Handler(std::map<std::string, T, Hash, Equal>* value)
: MapHandler<std::map<std::string, T, Hash, Equal>>(value)
{
}
std::string type_name() const override
{
return "std::map<std::string, " + this->internal_handler.type_name() + ">";
}
};
template <class T, class Hash, class Equal>
class Handler<std::unordered_multimap<std::string, T, Hash, Equal>>
: public MapHandler<std::unordered_multimap<std::string, T, Hash, Equal>>
{
public:
explicit Handler(std::unordered_multimap<std::string, T, Hash, Equal>* value)
: MapHandler<std::unordered_multimap<std::string, T, Hash, Equal>>(value)
{
}
std::string type_name() const override
{
return "std::unordered_mulitimap<std::string, " + this->internal_handler.type_name() + ">";
}
};
template <class T, class Hash, class Equal>
class Handler<std::multimap<std::string, T, Hash, Equal>>
: public MapHandler<std::multimap<std::string, T, Hash, Equal>>
{
public:
explicit Handler(std::multimap<std::string, T, Hash, Equal>* value)
: MapHandler<std::multimap<std::string, T, Hash, Equal>>(value)
{
}
std::string type_name() const override
{
return "std::multimap<std::string, " + this->internal_handler.type_name() + ">";
}
};
template <std::size_t N>
class TupleHander : public BaseHandler
{
protected:
std::array<std::unique_ptr<BaseHandler>, N> handlers;
std::size_t index = 0;
int depth = 0;
bool postcheck(bool success)
{
if (!success)
{
the_error.reset(new error::ArrayElementError(index));
return false;
}
if (handlers[index]->is_parsed())
{
++index;
}
return true;
}
protected:
void reset() override
{
index = 0;
depth = 0;
for (auto&& h : handlers)
h->prepare_for_reuse();
}
public:
bool Null() override
{
if (index >= N)
return true;
return postcheck(handlers[index]->Null());
}
bool Bool(bool b) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->Bool(b));
}
bool Int(int i) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->Int(i));
}
bool Uint(unsigned i) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->Uint(i));
}
bool Int64(std::int64_t i) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->Int64(i));
}
bool Uint64(std::uint64_t i) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->Uint64(i));
}
bool Double(double d) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->Double(d));
}
bool String(const char* str, SizeType length, bool copy) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->String(str, length, copy));
}
bool Key(const char* str, SizeType length, bool copy) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->Key(str, length, copy));
}
bool StartArray() override
{
if (++depth > 1)
{
if (index >= N)
return true;
return postcheck(handlers[index]->StartArray());
}
return true;
}
bool EndArray(SizeType length) override
{
if (--depth > 0)
{
if (index >= N)
return true;
return postcheck(handlers[index]->EndArray(length));
}
this->parsed = true;
return true;
}
bool StartObject() override
{
if (index >= N)
return true;
return postcheck(handlers[index]->StartObject());
}
bool EndObject(SizeType length) override
{
if (index >= N)
return true;
return postcheck(handlers[index]->EndObject(length));
}
bool reap_error(ErrorStack& errs) override
{
if (!this->the_error)
return false;
errs.push(this->the_error.release());
for (auto&& h : handlers)
h->reap_error(errs);
return true;
}
bool write(IHandler* out) const override
{
if (!out->StartArray())
return false;
for (auto&& h : handlers)
{
if (!h->write(out))
return false;
}
return out->EndArray(N);
}
void generate_schema(Value& output, MemoryPoolAllocator& alloc) const override
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("array"), alloc);
Value items(rapidjson::kArrayType);
for (auto&& h : handlers)
{
Value item;
h->generate_schema(item, alloc);
items.PushBack(item, alloc);
}
output.AddMember(rapidjson::StringRef("items"), items, alloc);
}
};
namespace nonpublic
{
template <std::size_t index, std::size_t N, typename Tuple>
struct TupleIniter
{
void operator()(std::unique_ptr<BaseHandler>* handlers, Tuple& t) const
{
handlers[index].reset(
new Handler<typename std::tuple_element<index, Tuple>::type>(&std::get<index>(t)));
TupleIniter<index + 1, N, Tuple>{}(handlers, t);
}
};
template <std::size_t N, typename Tuple>
struct TupleIniter<N, N, Tuple>
{
void operator()(std::unique_ptr<BaseHandler>* handlers, Tuple& t) const
{
(void)handlers;
(void)t;
}
};
}
template <typename... Ts>
class Handler<std::tuple<Ts...>> : public TupleHander<std::tuple_size<std::tuple<Ts...>>::value>
{
private:
static const std::size_t N = std::tuple_size<std::tuple<Ts...>>::value;
public:
explicit Handler(std::tuple<Ts...>* t)
{
nonpublic::TupleIniter<0, N, std::tuple<Ts...>> initer;
initer(this->handlers.data(), *t);
}
std::string type_name() const override
{
std::string str = "std::tuple<";
for (auto&& h : this->handlers)
{
str += h->type_name();
str += ", ";
}
str.pop_back();
str.pop_back();
str += '>';
return str;
}
};
}
================================================
FILE: src/staticjson.cpp
================================================
#include <staticjson/document.hpp>
#include <staticjson/staticjson.hpp>
#include <rapidjson/error/en.h>
#include <rapidjson/error/error.h>
#include <rapidjson/filereadstream.h>
#include <rapidjson/filewritestream.h>
#include <rapidjson/prettywriter.h>
#include <rapidjson/reader.h>
#include <rapidjson/writer.h>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <exception>
#include <new>
namespace staticjson
{
// Adapted from Jettison's implementation (http://jettison.codehaus.org/)
// Original copyright (compatible with MIT):
// Copyright 2006 Envoi Solutions LLC
//
// 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.
inline std::string quote(const std::string& str)
{
std::string sb;
sb.reserve(str.size() + 8);
sb += '\"';
typedef std::string::const_iterator iterator;
for (iterator it = str.begin(), end = str.end(); it != end; ++it)
{
char c = *it;
switch (c)
{
case '\\':
case '"':
sb += '\\';
sb += c;
break;
case '\b':
sb.append("\\b", 2);
break;
case '\t':
sb.append("\\t", 2);
break;
case '\n':
sb.append("\\n", 2);
break;
case '\f':
sb.append("\\f", 2);
break;
case '\r':
sb.append("\\r", 2);
break;
case '\x00':
sb.append("\\x00", 4);
break;
case '\x01':
sb.append("\\x01", 4);
break;
case '\x02':
sb.append("\\x02", 4);
break;
case '\x03':
sb.append("\\x03", 4);
break;
case '\x04':
sb.append("\\x04", 4);
break;
case '\x05':
sb.append("\\x05", 4);
break;
case '\x06':
sb.append("\\x06", 4);
break;
case '\x07':
sb.append("\\x07", 4);
break;
case '\x0b':
sb.append("\\x0b", 4);
break;
case '\x0e':
sb.append("\\x0e", 4);
break;
case '\x0f':
sb.append("\\x0f", 4);
break;
case '\x10':
sb.append("\\x10", 4);
break;
case '\x11':
sb.append("\\x11", 4);
break;
case '\x12':
sb.append("\\x12", 4);
break;
case '\x13':
sb.append("\\x13", 4);
break;
case '\x14':
sb.append("\\x14", 4);
break;
case '\x15':
sb.append("\\x15", 4);
break;
case '\x16':
sb.append("\\x16", 4);
break;
case '\x17':
sb.append("\\x17", 4);
break;
case '\x18':
sb.append("\\x18", 4);
break;
case '\x19':
sb.append("\\x19", 4);
break;
case '\x1a':
sb.append("\\x1a", 4);
break;
case '\x1b':
sb.append("\\x1b", 4);
break;
case '\x1c':
sb.append("\\x1c", 4);
break;
case '\x1d':
sb.append("\\x1d", 4);
break;
case '\x1e':
sb.append("\\x1e", 4);
break;
case '\x1f':
sb.append("\\x1f", 4);
break;
default:
sb += c;
}
}
sb += '\"';
return sb;
}
static std::string stringprintf(const char* format, ...)
#ifndef _MSC_VER
__attribute__((format(printf, 1, 2)))
#endif
;
static std::string stringprintf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
int sz = vsnprintf(nullptr, 0, format, ap);
va_end(ap);
if (sz <= 0)
return std::string();
std::string result(sz, 0);
va_start(ap, format);
vsnprintf(&result[0], static_cast<size_t>(sz + 1), format, ap);
va_end(ap);
return result;
}
std::string error::Success::description() const { return "No error"; }
std::string error::ObjectMemberError::description() const
{
return "Error at object member with name " + quote(member_name());
}
std::string error::ArrayElementError::description() const
{
return "Error at array element at index " + std::to_string(index());
}
std::string error::RequiredFieldMissingError::description() const
{
std::string result = "Missing required field(s): ";
bool first = true;
for (auto&& name : missing_members())
{
if (!first)
{
result += ", ";
}
first = false;
result += quote(name);
}
return result;
}
std::string error::NumberOutOfRangeError::description() const
{
return "Number out of range: expected type " + quote(expected_type())
+ " but the type needed is " + quote(actual_type());
}
std::string error::TypeMismatchError::description() const
{
return "Type mismatch between expected type " + quote(expected_type()) + " and actual type "
+ quote(actual_type());
}
std::string error::DuplicateKeyError::description() const
{
return "Duplicate key in uniquely keyed map type: " + quote(key());
}
std::string error::UnknownFieldError::description() const
{
return "Unknown field with name: " + quote(field_name());
}
std::string error::RecursionTooDeepError::description() const
{
return "Too many levels of recursion";
}
std::string error::TooManyLeavesError::description() const { return "Too many leaves"; }
std::string error::CorruptedDOMError::description() const { return "JSON has invalid structure"; }
std::string error::ArrayLengthMismatchError::description() const
{
return "The JSON array has different length than the required type";
}
std::string error::InvalidEnumError::description() const
{
return quote(m_name) + " is an invalid enum name";
}
std::string error::CustomError::description() const { return m_message; }
std::string ParseStatus::short_description() const
{
if (!has_error())
{
return std::string();
}
return stringprintf(
"Parsing failed at offset %lld with error code %d:\n%s\n",
static_cast<long long>(m_offset),
m_code,
rapidjson::GetParseError_En(static_cast<rapidjson::ParseErrorCode>(m_code)));
}
std::string ParseStatus::description() const
{
std::string res = short_description();
if (m_stack)
{
res += "\nTraceback (last call first)\n";
for (auto&& err : m_stack)
{
res += "* ";
res += err.description();
res += '\n';
}
}
return res;
}
IHandler::~IHandler() {}
BaseHandler::~BaseHandler() {}
bool BaseHandler::set_out_of_range(const char* actual_type)
{
the_error.reset(new error::NumberOutOfRangeError(type_name(), actual_type));
return false;
}
bool BaseHandler::set_type_mismatch(const char* actual_type)
{
the_error.reset(new error::TypeMismatchError(type_name(), actual_type));
return false;
}
bool IHandler::RawNumber(const char*, SizeType, bool)
{
fprintf(stderr, "%s", "Calling non-overridden IHandler::RawNumber() is a programming bug!\n");
std::terminate();
}
ObjectHandler::ObjectHandler()
: memory_pool_allocator(GlobalConfig::getInstance()->getMemoryChunkSize(),
&mempool::get_crt_allocator())
, internals(decltype(internals)::allocator_type(&memory_pool_allocator))
, current_name(decltype(current_name)::allocator_type(&memory_pool_allocator))
, leavesStack(decltype(leavesStack)::container_type::allocator_type(&memory_pool_allocator))
{
}
ObjectHandler::~ObjectHandler() {}
std::string ObjectHandler::type_name() const { return "object"; }
void ObjectHandler::postinit()
{
size_t max_string_size = 0;
for (const auto& pair : internals)
{
max_string_size = std::max<size_t>(max_string_size, pair.first.size());
}
if (max_string_size)
{
current_name.reserve(max_string_size);
}
}
bool ObjectHandler::precheck(const char* actual_type)
{
if (depth <= 0)
{
the_error.reset(new error::TypeMismatchError(type_name(), actual_type));
return false;
}
if (current && current->handler && current->handler->is_parsed())
{
if (flags & Flags::AllowDuplicateKey)
{
current->handler->prepare_for_reuse();
}
else
{
the_error.reset(new error::DuplicateKeyError(mempool::to_std_string(current_name)));
return false;
}
}
return true;
}
bool ObjectHandler::postcheck(bool success)
{
if (!success)
{
the_error.reset(new error::ObjectMemberError(mempool::to_std_string(current_name)));
}
return success;
}
void ObjectHandler::set_missing_required(const std::string& name)
{
if (!the_error || the_error->type() != error::MISSING_REQUIRED)
the_error.reset(new error::RequiredFieldMissingError());
std::vector<std::string>& missing
= static_cast<error::RequiredFieldMissingError*>(the_error.get())->missing_members();
missing.push_back(name);
}
#define POSTCHECK(x) (!current || !(current->handler) || postcheck(x))
bool ObjectHandler::Double(double value)
{
if (!precheck("double"))
return false;
return POSTCHECK(current->handler->Double(value));
}
bool ObjectHandler::Int(int value)
{
if (!precheck("int"))
return false;
return POSTCHECK(current->handler->Int(value));
}
bool ObjectHandler::Uint(unsigned value)
{
if (!precheck("unsigned"))
return false;
return POSTCHECK(current->handler->Uint(value));
}
bool ObjectHandler::Bool(bool value)
{
if (!precheck("bool"))
return false;
return POSTCHECK(current->handler->Bool(value));
}
bool ObjectHandler::Int64(std::int64_t value)
{
if (!precheck("std::int64_t"))
return false;
return POSTCHECK(current->handler->Int64(value));
}
bool ObjectHandler::Uint64(std::uint64_t value)
{
if (!precheck("std::uint64_t"))
return false;
return POSTCHECK(current->handler->Uint64(value));
}
bool ObjectHandler::Null()
{
if (!precheck("null"))
return false;
return POSTCHECK(current->handler->Null());
}
bool ObjectHandler::StartCheckMaxDepthMaxLeaves(bool isArray)
{
if (GlobalConfig::getInstance()->isMaxDepthSet())
{
++jsonDepth;
// If a leaf IE is an array of a simple data type, then the whole array shall be considered
// as the first level of nesting. If a leaf IE is a data structure or an array of data
// structures, then it shall be considered a branch and the first level of nesting.
if (jsonDepth > GlobalConfig::getInstance()->getMaxDepth())
{
if (!the_error || the_error->type() != error::TOO_DEEP_RECURSION)
the_error.reset(new error::RecursionTooDeepError());
jsonDepth = 0;
return false;
}
}
if (GlobalConfig::getInstance()->isMaxLeavesSet())
{
if (isArray)
{
lastLeafStat = true;
}
else
{
lastLeafStat = false;
}
leavesStack.push(0);
}
return true;
}
bool ObjectHandler::EndCheckMaxDepthMaxLeaves(SizeType sz, bool isArray)
{
if (GlobalConfig::getInstance()->isMaxDepthSet())
{
--jsonDepth;
}
if (GlobalConfig::getInstance()->isMaxLeavesSet())
{
if (isArray)
{
if (lastLeafStat && sz > 0)
{
// simple array type
// sz > 0 check if it is an empty array, and should not increase total leaf number
// for empty array
// TS29501 chapter 6.2
// If a leaf IE is an array of a simple data type, then the whole array shall count
// as one leaf.
totalLeaves += 1;
}
}
else
{
// object type
totalLeaves += sz;
totalLeaves -= leavesStack.top();
}
if (totalLeaves > GlobalConfig::getInstance()->getMaxLeaves())
{
if (!the_error || the_error->type() != error::TOO_MANY_LEAVES)
the_error.reset(new error::TooManyLeavesError());
totalLeaves = 0;
return false;
}
leavesStack.pop();
if (!leavesStack.empty())
{
leavesStack.top()++;
}
lastLeafStat = false;
}
return true;
}
bool ObjectHandler::StartArray()
{
if (!StartCheckMaxDepthMaxLeaves(true))
return false;
if (!precheck("array"))
return false;
return POSTCHECK(current->handler->StartArray());
}
bool ObjectHandler::EndArray(SizeType sz)
{
if (!EndCheckMaxDepthMaxLeaves(sz, true))
return false;
if (!precheck("array"))
return false;
return POSTCHECK(current->handler->EndArray(sz));
}
bool ObjectHandler::String(const char* str, SizeType sz, bool copy)
{
if (!precheck("string"))
return false;
return POSTCHECK(current->handler->String(str, sz, copy));
}
bool ObjectHandler::Key(const char* str, SizeType sz, bool copy)
{
if (depth <= 0)
{
the_error.reset(new error::CorruptedDOMError());
return false;
}
if (depth == 1)
{
current_name.assign(str, sz);
auto it = internals.find(current_name);
if (it == internals.end())
{
current = nullptr;
if ((flags & Flags::DisallowUnknownKey))
{
the_error.reset(new error::UnknownFieldError(str, sz));
return false;
}
}
else if (it->second.flags & Flags::IgnoreRead)
{
current = nullptr;
}
else
{
current = &it->second;
}
return true;
}
else
{
return POSTCHECK(current->handler->Key(str, sz, copy));
}
}
bool ObjectHandler::StartObject()
{
++depth;
if (!StartCheckMaxDepthMaxLeaves(false))
{
return false;
}
if (depth > 1)
{
return POSTCHECK(current->handler->StartObject());
}
return true;
}
bool ObjectHandler::EndObject(SizeType sz)
{
--depth;
if (!EndCheckMaxDepthMaxLeaves(sz, false))
{
return false;
}
if (depth > 0)
{
return POSTCHECK(current->handler->EndObject(sz));
}
for (auto&& pair : internals)
{
if (pair.second.handler && !(pair.second.flags & Flags::Optional)
&& !pair.second.handler->is_parsed())
{
set_missing_required(mempool::to_std_string(pair.first));
}
}
if (!the_error)
{
this->parsed = true;
return true;
}
return false;
}
void ObjectHandler::reset()
{
current = nullptr;
current_name.clear();
depth = 0;
for (auto&& pair : internals)
{
if (pair.second.handler)
pair.second.handler->prepare_for_reuse();
}
}
void ObjectHandler::add_handler(mempool::String&& name, ObjectHandler::FlaggedHandler&& fh)
{
internals.emplace(std::move(name), std::move(fh));
}
bool ObjectHandler::reap_error(ErrorStack& stack)
{
if (!the_error)
return false;
stack.push(the_error.release());
if (current && current->handler)
current->handler->reap_error(stack);
return true;
}
bool ObjectHandler::write(IHandler* output) const
{
SizeType count = 0;
if (!output->StartObject())
return false;
for (auto&& pair : internals)
{
if (!pair.second.handler || (pair.second.flags & Flags::IgnoreWrite))
continue;
if (!output->Key(
pair.first.data(), static_cast<staticjson::SizeType>(pair.first.size()), true))
return false;
if (!pair.second.handler->write(output))
return false;
++count;
}
return output->EndObject(count);
}
void ObjectHandler::generate_schema(Value& output, MemoryPoolAllocator& alloc) const
{
output.SetObject();
output.AddMember(rapidjson::StringRef("type"), rapidjson::StringRef("object"), alloc);
Value properties(rapidjson::kObjectType);
Value required(rapidjson::kArrayType);
for (auto&& pair : internals)
{
Value schema;
if (pair.second.handler)
pair.second.handler->generate_schema(schema, alloc);
else
std::abort();
Value key;
key.SetString(pair.first.c_str(), static_cast<SizeType>(pair.first.size()), alloc);
properties.AddMember(key, schema, alloc);
if (!(pair.second.flags & Flags::Optional))
{
key.SetString(pair.first.c_str(), static_cast<SizeType>(pair.first.size()), alloc);
required.PushBack(key, alloc);
}
}
output.AddMember(rapidjson::StringRef("properties"), properties, alloc);
if (!required.Empty())
{
output.AddMember(rapidjson::StringRef("required"), required, alloc);
}
output.AddMember(rapidjson::StringRef("additionalProperties"),
!(get_flags() & Flags::DisallowUnknownKey),
alloc);
}
namespace nonpublic
{
template <class T>
class IHandlerAdapter : public IHandler
{
private:
T* t;
public:
explicit IHandlerAdapter(T* t) : t(t) {}
virtual bool Null() override { return t->Null(); }
virtual bool Bool(bool v) override { return t->Bool(v); }
virtual bool Int(int v) override { return t->Int(v); }
virtual bool Uint(unsigned v) override { return t->Uint(v); }
virtual bool Int64(std::int64_t v) override { return t->Int64(v); }
virtual bool Uint64(std::uint64_t v) override { return t->Uint64(v); }
virtual bool Double(double v) override { return t->Double(v); }
virtual bool String(const char* str, SizeType sz, bool copy) override
{
return t->String(str, sz, copy);
}
virtual bool StartObject() override { return t->StartObject(); }
virtual bool Key(const char* str, SizeType sz, bool copy) override
{
return t->Key(str, sz, copy);
}
virtual bool EndObject(SizeType sz) override { return t->EndObject(sz); }
virtual bool StartArray() override { return t->StartArray(); }
virtual bool EndArray(SizeType sz) override { return t->EndArray(sz); }
virtual void prepare_for_reuse() override { std::terminate(); }
};
template <class InputStream>
static bool read_json(InputStream& is, BaseHandler* h, ParseStatus* status)
{
rapidjson::Reader r;
rapidjson::ParseResult rc = r.Parse(is, *h);
if (status)
{
status->set_result(rc.Code(), rc.Offset());
h->reap_error(status->error_stack());
}
return rc.Code() == 0;
}
bool parse_json_string(const char* str, BaseHandler* handler, ParseStatus* status)
{
rapidjson::StringStream is(str);
return read_json(is, handler, status);
}
bool parse_json_file(std::FILE* fp, BaseHandler* handler, ParseStatus* status)
{
if (!fp)
return false;
char buffer[1000];
rapidjson::FileReadStream is(fp, buffer, sizeof(buffer));
return read_json(is, handler, status);
}
struct StringOutputStream : private NonMobile
{
typedef char Ch;
std::string* str;
void Put(char c) { str->push_back(c); }
void Flush() {}
};
std::string serialize_json_string(const BaseHandler* handler)
{
std::string result;
StringOutputStream os;
os.str = &result;
rapidjson::Writer<StringOutputStream> writer(os);
IHandlerAdapter<decltype(writer)> adapter(&writer);
handler->write(&adapter);
return result;
}
bool serialize_json_file(std::FILE* fp, const BaseHandler* handler)
{
if (!fp)
return false;
char buffer[1000];
rapidjson::FileWriteStream os(fp, buffer, sizeof(buffer));
rapidjson::Writer<rapidjson::FileWriteStream> writer(os);
IHandlerAdapter<decltype(writer)> adapter(&writer);
return handler->write(&adapter);
}
std::string serialize_pretty_json_string(const BaseHandler* handler)
{
std::string result;
StringOutputStream os;
os.str = &result;
rapidjson::PrettyWriter<StringOutputStream> writer(os);
IHandlerAdapter<decltype(writer)> adapter(&writer);
handler->write(&adapter);
result.push_back('\n');
return result;
}
bool serialize_pretty_json_file(std::FILE* fp, const BaseHandler* handler)
{
if (!fp)
return false;
char buffer[1000];
rapidjson::FileWriteStream os(fp, buffer, sizeof(buffer));
rapidjson::PrettyWriter<rapidjson::FileWriteStream> writer(os);
IHandlerAdapter<decltype(writer)> adapter(&writer);
bool res = handler->write(&adapter);
if (res)
{
putc('\n', fp);
}
return res;
}
bool write_value(const Value& v, BaseHandler* out, ParseStatus* status)
{
if (!v.Accept(*static_cast<IHandler*>(out)))
{
if (status)
{
status->set_result(rapidjson::kParseErrorTermination, 0);
out->reap_error(status->error_stack());
}
return false;
}
return true;
}
bool
read_value(Value* v, MemoryPoolAllocator* alloc, const BaseHandler* input, ParseStatus* status)
{
JSONHandler handler(v, alloc);
if (!input->write(&handler))
{
if (status)
{
status->set_result(rapidjson::kParseErrorTermination, 0);
handler.reap_error(status->error_stack());
}
return false;
}
return true;
}
}
JSONHandler::JSONHandler(Value* v, MemoryPoolAllocator* a) : m_stack(), m_value(v), m_alloc(a)
{
m_stack.reserve(25);
}
bool JSONHandler::set_corrupted_dom()
{
the_error.reset(new error::CorruptedDOMError());
return false;
}
std::string JSONHandler::type_name() const { return "JSON"; }
bool JSONHandler::stack_push()
{
m_stack.emplace_back();
return true;
}
void JSONHandler::stack_pop()
{
if (!m_stack.empty())
m_stack.pop_back();
}
Value& JSONHandler::stack_top()
{
if (m_stack.empty())
return *m_value;
return m_stack.back();
}
bool JSONHandler::postprocess()
{
if (m_stack.empty())
{
this->parsed = true;
return true;
}
Value top1(std::move(stack_top()));
stack_pop();
if (stack_top().IsArray())
{
stack_top().PushBack(top1, *m_alloc);
return stack_push();
}
else if (stack_top().IsString())
{
Value key(std::move(stack_top()));
stack_pop();
if (!stack_top().IsObject())
return set_corrupted_dom();
stack_top().AddMember(key, top1, *m_alloc);
return true;
}
return set_corrupted_dom();
}
bool JSONHandler::Null()
{
stack_top().SetNull();
return postprocess();
}
bool JSONHandler::Bool(bool b)
{
stack_top().SetBool(b);
return postprocess();
}
bool JSONHandler::Double(double d)
{
stack_top().SetDouble(d);
return postprocess();
}
bool JSONHandler::Int(int i)
{
stack_top().SetInt(i);
return postprocess();
}
bool JSONHandler::Int64(std::int64_t i)
{
stack_top().SetInt64(i);
return postprocess();
}
bool JSONHandler::Uint(unsigned int i)
{
stack_top().SetUint(i);
return postprocess();
}
bool JSONHandler::Uint64(std::uint64_t i)
{
stack_top().SetUint64(i);
return postprocess();
}
bool JSONHandler::String(const char* str, SizeType sz, bool copy)
{
if (copy)
stack_top().SetString(str, sz, *m_alloc);
else
stack_top().SetString(str, sz);
return postprocess();
}
bool JSONHandler::Key(const char* str, SizeType sz, bool copy)
{
if (!stack_top().IsObject())
return set_corrupted_dom();
if (!stack_push())
return false;
if (copy)
stack_top().SetString(str, sz, *m_alloc);
else
stack_top().SetString(str, sz);
return stack_push();
}
bool JSONHandler::StartArray()
{
stack_top().SetArray();
return stack_push();
}
bool JSONHandler::EndArray(SizeType)
{
stack_pop();
if (!stack_top().IsArray())
return set_corrupted_dom();
return postprocess();
}
bool JSONHandler::StartObject()
{
stack_top().SetObject();
return true;
}
bool JSONHandler::EndObject(SizeType)
{
if (!stack_top().IsObject())
return set_corrupted_dom();
return postprocess();
}
void JSONHandler::reset(MemoryPoolAllocator* a)
{
for (Value& v : m_stack)
{
v.SetNull();
}
m_stack.clear();
m_alloc = a;
}
void JSONHandler::reset()
{
// Not implemented. See https://github.com/netheril96/StaticJSON/issues/41.
std::terminate();
}
bool JSONHandler::write(IHandler* output) const { return m_value->Accept(*output); }
GlobalConfig* GlobalConfig::getInstance() noexcept
{
static GlobalConfig config;
return &config;
}
namespace mempool
{
[[noreturn]] void throw_bad_alloc()
{
#ifdef __cpp_exceptions
throw std::bad_alloc();
#else
abort();
#endif
}
rapidjson::CrtAllocator& get_crt_allocator() noexcept
{
static rapidjson::CrtAllocator a;
return a;
}
}
}
================================================
FILE: test/myarray.hpp
================================================
#include <deque>
#include <staticjson/staticjson.hpp>
// This class is used to test custom conversion functions in StaticJSON.
template <class T>
class Array
{
private:
T* m_data;
size_t m_size;
public:
explicit Array() : m_data(nullptr), m_size(0) {}
explicit Array(size_t size) : m_size(size) { m_data = new T[size]; }
~Array() { clear(); }
Array(Array&& that) noexcept
{
m_data = that.m_data;
m_size = that.m_size;
that.m_data = nullptr;
that.m_size = 0;
}
Array& operator=(Array&& that) noexcept
{
std::swap(m_data, that.m_data);
std::swap(m_size, that.m_size);
return *this;
}
const T& operator[](size_t i) const { return m_data[i]; }
T& operator[](size_t i) { return m_data[i]; }
size_t size() const { return m_size; }
const T& back() const { return m_data[m_size - 1]; }
T& back() { return m_data[m_size - 1]; }
const T& front() const { return m_data[0]; }
T& front() { return m_data[0]; }
bool empty() const { return m_size == 0; }
void clear()
{
delete[] m_data;
m_data = nullptr;
m_size = 0;
}
};
namespace staticjson
{
template <class T>
struct Converter<Array<T>>
{
typedef std::deque<T> shadow_type;
static std::unique_ptr<ErrorBase> from_shadow(const shadow_type& shadow, Array<T>& value)
{
value = Array<T>(shadow.size());
for (size_t i = 0; i < shadow.size(); ++i)
{
value[i] = shadow[i];
}
return nullptr;
}
static void to_shadow(const Array<T>& value, shadow_type& shadow)
{
shadow.resize(value.size());
for (size_t i = 0; i < shadow.size(); ++i)
{
shadow[i] = value[i];
}
}
};
}
================================================
FILE: test/test_autojsoncxx.cpp
================================================
// The MIT License (MIT)
//
// Copyright (c) 2014 Siyuan Ren (netheril96@gmail.com)
//
// 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.
#include "catch.hpp"
#define AUTOJSONCXX_ROOT_DIRECTORY get_base_dir() + "/autojsoncxx/" +
#include <autojsoncxx.hpp>
#include "userdef.hpp"
#include <fstream>
#include <stack>
using namespace autojsoncxx;
using namespace config;
using namespace config::event;
const std::string& get_base_dir(void);
namespace config
{
inline bool opera
gitextract_e730zr57/
├── .cmake-format.py
├── .github/
│ └── workflows/
│ └── ccpp.yaml
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── _clang-format
├── autojsoncxx/
│ ├── autojsoncxx.hpp
│ ├── autojsoncxx.py
│ ├── examples/
│ │ ├── failure/
│ │ │ ├── duplicate_key.json
│ │ │ ├── duplicate_key_user.json
│ │ │ ├── hard.json
│ │ │ ├── integer_string.json
│ │ │ ├── map_element_mismatch.json
│ │ │ ├── missing_required.json
│ │ │ ├── null_in_key.json
│ │ │ ├── out_of_range.json
│ │ │ ├── single_object.json
│ │ │ └── unknown_field.json
│ │ └── success/
│ │ ├── hard.json
│ │ ├── user_array.json
│ │ ├── user_array_compact.json
│ │ └── user_map.json
│ ├── userdef.hpp
│ └── userdef.json
├── cmake/
│ └── staticjson-config.cmake.in
├── examples/
│ ├── failure/
│ │ ├── duplicate_key.json
│ │ ├── duplicate_key_user.json
│ │ ├── hard.json
│ │ ├── integer_string.json
│ │ ├── invalid_enum.json
│ │ ├── map_element_mismatch.json
│ │ ├── missing_required.json
│ │ ├── null_in_key.json
│ │ ├── out_of_range.json
│ │ ├── single_object.json
│ │ ├── tensor_length_error.json
│ │ ├── tensor_type_mismatch.json
│ │ └── unknown_field.json
│ └── success/
│ ├── hard.json
│ ├── tensor.json
│ ├── user_array.json
│ ├── user_array_compact.json
│ └── user_map.json
├── format.sh
├── include/
│ └── staticjson/
│ ├── basic.hpp
│ ├── document.hpp
│ ├── enum.hpp
│ ├── error.hpp
│ ├── forward_declarations.hpp
│ ├── io.hpp
│ ├── optional_support.hpp
│ ├── primitive_types.hpp
│ ├── staticjson.hpp
│ └── stl_types.hpp
├── src/
│ └── staticjson.cpp
└── test/
├── myarray.hpp
├── test_autojsoncxx.cpp
├── test_basic.cpp
├── test_example.cpp
├── test_instantiation.cpp
├── test_integration.cpp
├── test_memory_usage.cpp
└── test_tensor.cpp
SYMBOL INDEX (619 symbols across 20 files)
FILE: autojsoncxx/autojsoncxx.hpp
type autojsoncxx (line 7) | namespace autojsoncxx
function to_json_string (line 19) | inline void to_json_string(std::string& output, const ValueType& value)
function to_pretty_json_string (line 25) | inline void to_pretty_json_string(std::string& output, const ValueType...
function from_json_string (line 31) | inline bool from_json_string(const char* str, ValueType& value, Parsin...
function from_json_string (line 37) | inline bool from_json_string(const std::string& str, ValueType& value,...
function from_json_file (line 43) | inline bool from_json_file(const char* str, ValueType& value, ParsingR...
function from_json_file (line 49) | inline bool from_json_file(const std::string& str, ValueType& value, P...
function from_json_file (line 55) | inline bool from_json_file(std::FILE* fp, ValueType& value, ParsingRes...
function to_document (line 61) | void to_document(const T& value, rapidjson::Document& doc)
function from_document (line 67) | bool from_document(T& value, const rapidjson::Document& doc, error::Er...
FILE: autojsoncxx/autojsoncxx.py
class InvalidDefinitionError (line 57) | class InvalidDefinitionError(Exception):
class InvalidIdentifier (line 61) | class InvalidIdentifier(InvalidDefinitionError):
method __init__ (line 62) | def __init__(self, identifier):
method __str__ (line 65) | def __str__(self):
class InvalidNamespace (line 69) | class InvalidNamespace(InvalidDefinitionError):
method __init__ (line 70) | def __init__(self, namespace):
method __str__ (line 73) | def __str__(self):
class UnrecognizedOption (line 77) | class UnrecognizedOption(InvalidDefinitionError):
method __init__ (line 78) | def __init__(self, option):
method __str__ (line 81) | def __str__(self):
class UnsupportedTypeError (line 85) | class UnsupportedTypeError(InvalidDefinitionError):
method __init__ (line 86) | def __init__(self, type_name):
method __str__ (line 89) | def __str__(self):
function cstring_literal (line 96) | def cstring_literal(byte_string):
function check_identifier (line 103) | def check_identifier(identifier):
class ClassInfo (line 108) | class ClassInfo(object):
method __init__ (line 111) | def __init__(self, record):
method name (line 129) | def name(self):
method qualified_name (line 133) | def qualified_name(self):
method members (line 141) | def members(self):
method strict_parsing (line 145) | def strict_parsing(self):
method namespace (line 149) | def namespace(self):
method constructor_code (line 153) | def constructor_code(self):
method no_duplicates (line 157) | def no_duplicates(self):
class ClassDefinitionCodeGenerator (line 161) | class ClassDefinitionCodeGenerator(object):
method __init__ (line 162) | def __init__(self, class_info):
method class_info (line 166) | def class_info(self):
method member_declarations (line 169) | def member_declarations(self):
method initializer_list (line 172) | def initializer_list(self):
method constructor (line 175) | def constructor(self):
method staticjson_init (line 180) | def staticjson_init(self):
method class_definition (line 197) | def class_definition(self):
class MemberInfo (line 210) | class MemberInfo(object):
method __init__ (line 213) | def __init__(self, record):
method type_name (line 230) | def type_name(self):
method variable_name (line 234) | def variable_name(self):
method json_key (line 238) | def json_key(self):
method is_required (line 245) | def is_required(self):
method default (line 252) | def default(self):
method constructor_args (line 259) | def constructor_args(self):
method add_property_statement (line 262) | def add_property_statement(self, handler_name):
method cpp_repr (line 268) | def cpp_repr(args):
function read_utf8 (line 285) | def read_utf8(filename):
function main (line 293) | def main():
FILE: autojsoncxx/userdef.hpp
type config (line 3) | namespace config
type Date (line 5) | struct Date
method Date (line 11) | explicit Date() : year(), month(), day() {}
method staticjson_init (line 13) | void staticjson_init(staticjson::ObjectHandler* h)
type event (line 27) | namespace event
type BlockEvent (line 29) | struct BlockEvent
method BlockEvent (line 37) | explicit BlockEvent()
method staticjson_init (line 51) | void staticjson_init(staticjson::ObjectHandler* h)
type User (line 69) | struct User
method User (line 78) | explicit User()
method staticjson_init (line 88) | void staticjson_init(staticjson::ObjectHandler* h)
type config (line 25) | namespace config
type Date (line 5) | struct Date
method Date (line 11) | explicit Date() : year(), month(), day() {}
method staticjson_init (line 13) | void staticjson_init(staticjson::ObjectHandler* h)
type event (line 27) | namespace event
type BlockEvent (line 29) | struct BlockEvent
method BlockEvent (line 37) | explicit BlockEvent()
method staticjson_init (line 51) | void staticjson_init(staticjson::ObjectHandler* h)
type User (line 69) | struct User
method User (line 78) | explicit User()
method staticjson_init (line 88) | void staticjson_init(staticjson::ObjectHandler* h)
type config (line 67) | namespace config
type Date (line 5) | struct Date
method Date (line 11) | explicit Date() : year(), month(), day() {}
method staticjson_init (line 13) | void staticjson_init(staticjson::ObjectHandler* h)
type event (line 27) | namespace event
type BlockEvent (line 29) | struct BlockEvent
method BlockEvent (line 37) | explicit BlockEvent()
method staticjson_init (line 51) | void staticjson_init(staticjson::ObjectHandler* h)
type User (line 69) | struct User
method User (line 78) | explicit User()
method staticjson_init (line 88) | void staticjson_init(staticjson::ObjectHandler* h)
FILE: include/staticjson/basic.hpp
type staticjson (line 14) | namespace staticjson
type NonMobile (line 16) | struct NonMobile
method NonMobile (line 18) | NonMobile() {}
method NonMobile (line 20) | NonMobile(const NonMobile&) = delete;
method NonMobile (line 21) | NonMobile(NonMobile&&) = delete;
method NonMobile (line 22) | NonMobile& operator=(const NonMobile&) = delete;
method NonMobile (line 23) | NonMobile& operator=(NonMobile&&) = delete;
class GlobalConfig (line 29) | class GlobalConfig : private NonMobile
method SizeType (line 33) | SizeType getMemoryChunkSize() const noexcept { return memoryChunkSiz...
method setMemoryChunkSize (line 34) | void setMemoryChunkSize(SizeType value) noexcept { memoryChunkSize =...
method setMaxLeaves (line 35) | void setMaxLeaves(SizeType maxNum) noexcept
method setMaxDepth (line 40) | void setMaxDepth(SizeType maxDep) noexcept
method SizeType (line 45) | SizeType getMaxDepth() const noexcept { return maxDepth; }
method SizeType (line 46) | SizeType getMaxLeaves() const noexcept { return maxLeaves; }
method isMaxLeavesSet (line 47) | bool isMaxLeavesSet() const noexcept { return _isMaxLeavesSet; }
method isMaxDepthSet (line 48) | bool isMaxDepthSet() const noexcept { return _isMaxDepthSet; }
method unsetMaxLeavesFlag (line 49) | void unsetMaxLeavesFlag() noexcept
method unsetMaxDepthFlag (line 54) | void unsetMaxDepthFlag() noexcept
method GlobalConfig (line 61) | GlobalConfig() {}
class IHandler (line 69) | class IHandler
method IHandler (line 72) | IHandler() {}
class BaseHandler (line 112) | class BaseHandler : public IHandler, private NonMobile
method reset (line 124) | virtual void reset() {}
method BaseHandler (line 127) | BaseHandler() {}
method Null (line 133) | virtual bool Null() override { return set_type_mismatch("null"); }
method Bool (line 135) | virtual bool Bool(bool) override { return set_type_mismatch("bool"); }
method Int (line 137) | virtual bool Int(int) override { return set_type_mismatch("int"); }
method Uint (line 139) | virtual bool Uint(unsigned) override { return set_type_mismatch("uns...
method Int64 (line 141) | virtual bool Int64(std::int64_t) override { return set_type_mismatch...
method Uint64 (line 143) | virtual bool Uint64(std::uint64_t) override { return set_type_mismat...
method Double (line 145) | virtual bool Double(double) override { return set_type_mismatch("dou...
method String (line 147) | virtual bool String(const char*, SizeType, bool) override
method StartObject (line 152) | virtual bool StartObject() override { return set_type_mismatch("obje...
method Key (line 154) | virtual bool Key(const char*, SizeType, bool) override { return set_...
method EndObject (line 156) | virtual bool EndObject(SizeType) override { return set_type_mismatch...
method StartArray (line 158) | virtual bool StartArray() override { return set_type_mismatch("array...
method EndArray (line 160) | virtual bool EndArray(SizeType) override { return set_type_mismatch(...
method has_error (line 162) | virtual bool has_error() const { return bool(the_error); }
method reap_error (line 164) | virtual bool reap_error(ErrorStack& errs)
method is_parsed (line 172) | bool is_parsed() const { return parsed; }
method prepare_for_reuse (line 174) | void prepare_for_reuse() override
type Flags (line 186) | struct Flags
class Handler (line 194) | class Handler
method Handler (line 569) | explicit Handler(T* t) : base_type(t) {}
type mempool (line 196) | namespace mempool
class PooledAllocator (line 202) | class PooledAllocator
method PooledAllocator (line 216) | explicit PooledAllocator(MemoryPoolAllocator* pool) noexcept : poo...
method PooledAllocator (line 219) | PooledAllocator(const PooledAllocator<U>& other) noexcept : pool(o...
method T (line 232) | T* allocate(const size_t n) const
method deallocate (line 245) | void deallocate(T* const p, size_t) const noexcept
function to_std_string (line 262) | inline std::string to_std_string(const String& str) { return {str.da...
type PooledDeleter (line 265) | struct PooledDeleter
function T (line 283) | T* pooled_new(MemoryPoolAllocator& pool, Args&&... args)
class ObjectHandler (line 294) | class ObjectHandler : public BaseHandler
type FlaggedHandler (line 297) | struct FlaggedHandler
method add_property (line 330) | void add_property(mempool::String name, T* pointer, unsigned flags_ ...
method get_flags (line 377) | unsigned get_flags() const { return flags; }
method set_flags (line 379) | void set_flags(unsigned f) { flags = f; }
method MemoryPoolAllocator (line 381) | const MemoryPoolAllocator& get_memory_pool() const noexcept { return...
method add_property (line 384) | void add_property(const std::string& name, T* pointer, unsigned flag...
method add_property (line 394) | void add_property(const char* name, T* pointer, unsigned flags_ = Fl...
type Converter (line 403) | struct Converter
method from_shadow (line 407) | static std::unique_ptr<ErrorBase> from_shadow(const shadow_type& sha...
method to_shadow (line 414) | static void to_shadow(const T& value, shadow_type& shadow)
method type_name (line 420) | static std::string type_name() { return "T"; }
function init (line 426) | void init(T* t, ObjectHandler* h)
class ObjectTypeHandler (line 432) | class ObjectTypeHandler : public ObjectHandler
method ObjectTypeHandler (line 435) | explicit ObjectTypeHandler(T* t)
class ConversionHandler (line 443) | class ConversionHandler : public BaseHandler
method postprocess (line 455) | bool postprocess(bool success)
method reset (line 473) | void reset() override
method ConversionHandler (line 480) | explicit ConversionHandler(T* t) : shadow(), internal(&shadow), m_va...
method type_name (line 482) | std::string type_name() const override
method Null (line 489) | virtual bool Null() override { return postprocess(internal.Null()); }
method Bool (line 491) | virtual bool Bool(bool b) override { return postprocess(internal.Boo...
method Int (line 493) | virtual bool Int(int i) override { return postprocess(internal.Int(i...
method Uint (line 495) | virtual bool Uint(unsigned u) override { return postprocess(internal...
method Int64 (line 497) | virtual bool Int64(std::int64_t i) override { return postprocess(int...
method Uint64 (line 499) | virtual bool Uint64(std::uint64_t u) override { return postprocess(i...
method Double (line 501) | virtual bool Double(double d) override { return postprocess(internal...
method String (line 503) | virtual bool String(const char* str, SizeType size, bool copy) override
method StartObject (line 508) | virtual bool StartObject() override { return postprocess(internal.St...
method Key (line 510) | virtual bool Key(const char* str, SizeType size, bool copy) override
method EndObject (line 515) | virtual bool EndObject(SizeType sz) override { return postprocess(in...
method StartArray (line 517) | virtual bool StartArray() override { return postprocess(internal.Sta...
method EndArray (line 519) | virtual bool EndArray(SizeType sz) override { return postprocess(int...
method has_error (line 521) | virtual bool has_error() const override
method reap_error (line 526) | bool reap_error(ErrorStack& errs) override
method write (line 531) | virtual bool write(IHandler* output) const override
method generate_schema (line 537) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
type helper (line 543) | namespace helper
class DispatchHandler (line 546) | class DispatchHandler
class DispatchHandler<T, true> (line 548) | class DispatchHandler<T, true> : public ::staticjson::ObjectTypeHand...
method DispatchHandler (line 551) | explicit DispatchHandler(T* t) : ::staticjson::ObjectTypeHandler<T...
class DispatchHandler<T, false> (line 555) | class DispatchHandler<T, false> : public ::staticjson::ConversionHan...
method DispatchHandler (line 558) | explicit DispatchHandler(T* t) : ::staticjson::ConversionHandler<T...
class Handler (line 563) | class Handler
method Handler (line 569) | explicit Handler(T* t) : base_type(t) {}
FILE: include/staticjson/document.hpp
type staticjson (line 8) | namespace staticjson
class JSONHandler (line 10) | class JSONHandler : public BaseHandler
method generate_schema (line 63) | void generate_schema(Value& output, MemoryPoolAllocator&) const over...
class Handler<Document> (line 67) | class Handler<Document> : public JSONHandler
method Handler (line 70) | explicit Handler(Document* h) : JSONHandler(h, &h->GetAllocator()) {}
method reset (line 71) | virtual void reset() override
type nonpublic (line 77) | namespace nonpublic
function from_json_value (line 85) | bool from_json_value(const Value& v, T* t, ParseStatus* status)
function from_json_document (line 92) | bool from_json_document(const Document& d,
function to_json_value (line 100) | bool to_json_value(Value* v, MemoryPoolAllocator* alloc, const T& t, P...
function to_json_document (line 107) | bool to_json_document(Document* d, const T& t, ParseStatus* status)
FILE: include/staticjson/enum.hpp
type staticjson (line 8) | namespace staticjson
class EnumHandler (line 11) | class EnumHandler : public BaseHandler
method EnumHandler (line 22) | explicit EnumHandler(Enum* value) : m_value(value) {}
method String (line 24) | bool String(const char* str, SizeType sz, bool) override
method write (line 40) | bool write(IHandler* output) const override
method generate_schema (line 54) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
FILE: include/staticjson/error.hpp
type staticjson (line 10) | namespace staticjson
class ErrorStack (line 14) | class ErrorStack
method ErrorStack (line 283) | explicit ErrorStack() : head(0), m_size(0) {}
method const_iterator (line 285) | const_iterator begin() const { return const_iterator(head); }
method const_iterator (line 287) | const_iterator end() const { return const_iterator(0); }
method push (line 291) | void push(ErrorBase* e)
method ErrorBase (line 303) | ErrorBase* pop()
method empty (line 315) | bool empty() const { return head == 0; }
method size (line 321) | std::size_t size() const { return m_size; }
method swap (line 333) | void swap(ErrorStack& other) noexcept
method ErrorStack (line 339) | ErrorStack(ErrorStack&& other) : head(other.head), m_size(other.m_size)
method ErrorStack (line 345) | ErrorStack& operator==(ErrorStack&& other)
class ErrorBase (line 15) | class ErrorBase
method ErrorBase (line 30) | explicit ErrorBase() : next(0) {}
method is_intermediate (line 40) | virtual bool is_intermediate() const { return false; }
type error (line 17) | namespace error
type internal (line 19) | namespace internal
class error_stack_const_iterator (line 21) | class error_stack_const_iterator
method error_stack_const_iterator (line 253) | explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
method reference (line 254) | reference operator*() const { return *e; }
method pointer (line 256) | pointer operator->() const { return e; }
method error_stack_const_iterator (line 258) | error_stack_const_iterator& operator++()
class error_stack_const_iterator (line 240) | class error_stack_const_iterator
method error_stack_const_iterator (line 253) | explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
method reference (line 254) | reference operator*() const { return *e; }
method pointer (line 256) | pointer operator->() const { return e; }
method error_stack_const_iterator (line 258) | error_stack_const_iterator& operator++()
class Success (line 55) | class Success : public ErrorBase
method Success (line 58) | explicit Success() {}
method error_type (line 60) | error_type type() const { return SUCCESS; }
class IntermediateError (line 63) | class IntermediateError : public ErrorBase
method is_intermediate (line 66) | bool is_intermediate() const { return true; }
class ObjectMemberError (line 69) | class ObjectMemberError : public IntermediateError
method ObjectMemberError (line 75) | explicit ObjectMemberError(std::string memberName) { m_member_name...
method error_type (line 81) | error_type type() const { return OBJECT_MEMBER; }
class ArrayElementError (line 84) | class ArrayElementError : public IntermediateError
method ArrayElementError (line 90) | explicit ArrayElementError(std::size_t idx) : m_index(idx) {}
method index (line 92) | std::size_t index() const { return m_index; }
method error_type (line 96) | error_type type() const { return ARRAY_ELEMENT; }
class RequiredFieldMissingError (line 99) | class RequiredFieldMissingError : public ErrorBase
method RequiredFieldMissingError (line 105) | explicit RequiredFieldMissingError() {}
method error_type (line 113) | error_type type() const { return MISSING_REQUIRED; }
class TypeMismatchError (line 116) | class TypeMismatchError : public ErrorBase
method TypeMismatchError (line 123) | explicit TypeMismatchError(std::string expectedType, std::string a...
method error_type (line 135) | error_type type() const { return TYPE_MISMATCH; }
class RecursionTooDeepError (line 138) | class RecursionTooDeepError : public ErrorBase
method error_type (line 141) | error_type type() const override { return TOO_DEEP_RECURSION; }
class TooManyLeavesError (line 143) | class TooManyLeavesError : public ErrorBase
method error_type (line 146) | error_type type() const override { return TOO_MANY_LEAVES; }
class NumberOutOfRangeError (line 148) | class NumberOutOfRangeError : public ErrorBase
method NumberOutOfRangeError (line 154) | explicit NumberOutOfRangeError(std::string expectedType, std::stri...
method error_type (line 166) | error_type type() const { return NUMBER_OUT_OF_RANGE; }
class DuplicateKeyError (line 169) | class DuplicateKeyError : public ErrorBase
method DuplicateKeyError (line 175) | explicit DuplicateKeyError(std::string name) { key_name.swap(name); }
method error_type (line 179) | error_type type() const { return DUPLICATE_KEYS; }
class UnknownFieldError (line 184) | class UnknownFieldError : public ErrorBase
method UnknownFieldError (line 190) | explicit UnknownFieldError(const char* name, std::size_t length) :...
method error_type (line 194) | error_type type() const { return UNKNOWN_FIELD; }
class CorruptedDOMError (line 199) | class CorruptedDOMError : public ErrorBase
method error_type (line 204) | error_type type() const { return CORRUPTED_DOM; }
class ArrayLengthMismatchError (line 207) | class ArrayLengthMismatchError : public ErrorBase
method error_type (line 212) | error_type type() const { return ARRAY_LENGTH_MISMATCH; }
class InvalidEnumError (line 215) | class InvalidEnumError : public ErrorBase
method InvalidEnumError (line 221) | explicit InvalidEnumError(std::string name) { m_name.swap(name); }
method error_type (line 223) | error_type type() const { return INVALID_ENUM; }
class CustomError (line 226) | class CustomError : public ErrorBase
method CustomError (line 232) | explicit CustomError(std::string message) { m_message.swap(message...
method error_type (line 234) | error_type type() const { return CUSTOM; }
type internal (line 237) | namespace internal
class error_stack_const_iterator (line 21) | class error_stack_const_iterator
method error_stack_const_iterator (line 253) | explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
method reference (line 254) | reference operator*() const { return *e; }
method pointer (line 256) | pointer operator->() const { return e; }
method error_stack_const_iterator (line 258) | error_stack_const_iterator& operator++()
class error_stack_const_iterator (line 240) | class error_stack_const_iterator
method error_stack_const_iterator (line 253) | explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
method reference (line 254) | reference operator*() const { return *e; }
method pointer (line 256) | pointer operator->() const { return e; }
method error_stack_const_iterator (line 258) | error_stack_const_iterator& operator++()
class ErrorBase (line 27) | class ErrorBase
method ErrorBase (line 30) | explicit ErrorBase() : next(0) {}
method is_intermediate (line 40) | virtual bool is_intermediate() const { return false; }
type error (line 45) | namespace error
type internal (line 19) | namespace internal
class error_stack_const_iterator (line 21) | class error_stack_const_iterator
method error_stack_const_iterator (line 253) | explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
method reference (line 254) | reference operator*() const { return *e; }
method pointer (line 256) | pointer operator->() const { return e; }
method error_stack_const_iterator (line 258) | error_stack_const_iterator& operator++()
class error_stack_const_iterator (line 240) | class error_stack_const_iterator
method error_stack_const_iterator (line 253) | explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
method reference (line 254) | reference operator*() const { return *e; }
method pointer (line 256) | pointer operator->() const { return e; }
method error_stack_const_iterator (line 258) | error_stack_const_iterator& operator++()
class Success (line 55) | class Success : public ErrorBase
method Success (line 58) | explicit Success() {}
method error_type (line 60) | error_type type() const { return SUCCESS; }
class IntermediateError (line 63) | class IntermediateError : public ErrorBase
method is_intermediate (line 66) | bool is_intermediate() const { return true; }
class ObjectMemberError (line 69) | class ObjectMemberError : public IntermediateError
method ObjectMemberError (line 75) | explicit ObjectMemberError(std::string memberName) { m_member_name...
method error_type (line 81) | error_type type() const { return OBJECT_MEMBER; }
class ArrayElementError (line 84) | class ArrayElementError : public IntermediateError
method ArrayElementError (line 90) | explicit ArrayElementError(std::size_t idx) : m_index(idx) {}
method index (line 92) | std::size_t index() const { return m_index; }
method error_type (line 96) | error_type type() const { return ARRAY_ELEMENT; }
class RequiredFieldMissingError (line 99) | class RequiredFieldMissingError : public ErrorBase
method RequiredFieldMissingError (line 105) | explicit RequiredFieldMissingError() {}
method error_type (line 113) | error_type type() const { return MISSING_REQUIRED; }
class TypeMismatchError (line 116) | class TypeMismatchError : public ErrorBase
method TypeMismatchError (line 123) | explicit TypeMismatchError(std::string expectedType, std::string a...
method error_type (line 135) | error_type type() const { return TYPE_MISMATCH; }
class RecursionTooDeepError (line 138) | class RecursionTooDeepError : public ErrorBase
method error_type (line 141) | error_type type() const override { return TOO_DEEP_RECURSION; }
class TooManyLeavesError (line 143) | class TooManyLeavesError : public ErrorBase
method error_type (line 146) | error_type type() const override { return TOO_MANY_LEAVES; }
class NumberOutOfRangeError (line 148) | class NumberOutOfRangeError : public ErrorBase
method NumberOutOfRangeError (line 154) | explicit NumberOutOfRangeError(std::string expectedType, std::stri...
method error_type (line 166) | error_type type() const { return NUMBER_OUT_OF_RANGE; }
class DuplicateKeyError (line 169) | class DuplicateKeyError : public ErrorBase
method DuplicateKeyError (line 175) | explicit DuplicateKeyError(std::string name) { key_name.swap(name); }
method error_type (line 179) | error_type type() const { return DUPLICATE_KEYS; }
class UnknownFieldError (line 184) | class UnknownFieldError : public ErrorBase
method UnknownFieldError (line 190) | explicit UnknownFieldError(const char* name, std::size_t length) :...
method error_type (line 194) | error_type type() const { return UNKNOWN_FIELD; }
class CorruptedDOMError (line 199) | class CorruptedDOMError : public ErrorBase
method error_type (line 204) | error_type type() const { return CORRUPTED_DOM; }
class ArrayLengthMismatchError (line 207) | class ArrayLengthMismatchError : public ErrorBase
method error_type (line 212) | error_type type() const { return ARRAY_LENGTH_MISMATCH; }
class InvalidEnumError (line 215) | class InvalidEnumError : public ErrorBase
method InvalidEnumError (line 221) | explicit InvalidEnumError(std::string name) { m_name.swap(name); }
method error_type (line 223) | error_type type() const { return INVALID_ENUM; }
class CustomError (line 226) | class CustomError : public ErrorBase
method CustomError (line 232) | explicit CustomError(std::string message) { m_message.swap(message...
method error_type (line 234) | error_type type() const { return CUSTOM; }
type internal (line 237) | namespace internal
class error_stack_const_iterator (line 21) | class error_stack_const_iterator
method error_stack_const_iterator (line 253) | explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
method reference (line 254) | reference operator*() const { return *e; }
method pointer (line 256) | pointer operator->() const { return e; }
method error_stack_const_iterator (line 258) | error_stack_const_iterator& operator++()
class error_stack_const_iterator (line 240) | class error_stack_const_iterator
method error_stack_const_iterator (line 253) | explicit error_stack_const_iterator(const ErrorBase* p) : e(p) {}
method reference (line 254) | reference operator*() const { return *e; }
method pointer (line 256) | pointer operator->() const { return e; }
method error_stack_const_iterator (line 258) | error_stack_const_iterator& operator++()
class ErrorStack (line 271) | class ErrorStack
method ErrorStack (line 283) | explicit ErrorStack() : head(0), m_size(0) {}
method const_iterator (line 285) | const_iterator begin() const { return const_iterator(head); }
method const_iterator (line 287) | const_iterator end() const { return const_iterator(0); }
method push (line 291) | void push(ErrorBase* e)
method ErrorBase (line 303) | ErrorBase* pop()
method empty (line 315) | bool empty() const { return head == 0; }
method size (line 321) | std::size_t size() const { return m_size; }
method swap (line 333) | void swap(ErrorStack& other) noexcept
method ErrorStack (line 339) | ErrorStack(ErrorStack&& other) : head(other.head), m_size(other.m_size)
method ErrorStack (line 345) | ErrorStack& operator==(ErrorStack&& other)
function swap (line 353) | inline void swap(ErrorStack& s1, ErrorStack& s2) { s1.swap(s2); }
class ParseStatus (line 355) | class ParseStatus
method ParseStatus (line 363) | explicit ParseStatus() : m_stack(), m_offset(), m_code() {}
method set_result (line 365) | void set_result(int err, std::size_t off)
method error_code (line 371) | int error_code() const { return m_code; }
method offset (line 373) | std::size_t offset() const { return m_offset; }
method ErrorStack (line 377) | ErrorStack& error_stack() { return m_stack; }
method ErrorStack (line 379) | const ErrorStack& error_stack() const { return m_stack; }
method const_iterator (line 383) | const_iterator begin() const { return m_stack.begin(); }
method const_iterator (line 385) | const_iterator end() const { return m_stack.end(); }
method has_error (line 387) | bool has_error() const { return m_code != 0 || !m_stack.empty(); }
method swap (line 391) | void swap(ParseStatus& other) noexcept
method ParseStatus (line 402) | ParseStatus(ParseStatus&& other) noexcept : m_stack(), m_offset(), m...
method ParseStatus (line 404) | ParseStatus& operator==(ParseStatus&& other) noexcept
function swap (line 412) | inline void swap(ParseStatus& r1, ParseStatus& r2) { r1.swap(r2); }
FILE: include/staticjson/forward_declarations.hpp
type staticjson (line 3) | namespace staticjson
class IHandler (line 7) | class IHandler
class BaseHandler (line 9) | class BaseHandler
class ObjectHandler (line 11) | class ObjectHandler
class Handler (line 14) | class Handler
FILE: include/staticjson/io.hpp
type staticjson (line 8) | namespace staticjson
type nonpublic (line 11) | namespace nonpublic
type FileGuard (line 20) | struct FileGuard : private NonMobile
method FileGuard (line 24) | explicit FileGuard(std::FILE* fp) : fp(fp) {}
function from_json_string (line 34) | inline bool from_json_string(const char* str, T* value, ParseStatus* s...
function from_json_file (line 41) | inline bool from_json_file(std::FILE* fp, T* value, ParseStatus* status)
function from_json_file (line 48) | inline bool from_json_file(const char* filename, T* value, ParseStatus...
function from_json_file (line 55) | inline bool from_json_file(const std::string& filename, T* value, Pars...
function to_json_string (line 61) | inline std::string to_json_string(const T& value)
function to_json_file (line 68) | inline bool to_json_file(std::FILE* fp, const T& value)
function to_json_file (line 75) | inline bool to_json_file(const char* filename, const T& value)
function to_json_file (line 82) | inline bool to_json_file(const std::string& filename, const T& value)
function to_pretty_json_string (line 88) | inline std::string to_pretty_json_string(const T& value)
function to_pretty_json_file (line 95) | inline bool to_pretty_json_file(std::FILE* fp, const T& value)
function to_pretty_json_file (line 102) | inline bool to_pretty_json_file(const char* filename, const T& value)
function to_pretty_json_file (line 109) | inline bool to_pretty_json_file(const std::string& filename, const T& ...
function Document (line 115) | inline Document export_json_schema(T* value, Document::AllocatorType* ...
FILE: include/staticjson/optional_support.hpp
type staticjson (line 9) | namespace staticjson
class Handler<optional<T>> (line 39) | class Handler<optional<T>> : public BaseHandler
method Handler (line 50) | explicit Handler(optional<T>* value) : m_value(value) {}
method initialize (line 53) | void initialize()
method reset (line 62) | void reset() override
method postcheck (line 69) | bool postcheck(bool success)
method Null (line 77) | bool Null() override
method write (line 92) | bool write(IHandler* out) const override
method generate_schema (line 105) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
method Bool (line 119) | bool Bool(bool b) override
method Int (line 125) | bool Int(int i) override
method Uint (line 131) | bool Uint(unsigned i) override
method Int64 (line 137) | bool Int64(std::int64_t i) override
method Uint64 (line 143) | bool Uint64(std::uint64_t i) override
method Double (line 149) | bool Double(double i) override
method String (line 155) | bool String(const char* str, SizeType len, bool copy) override
method Key (line 161) | bool Key(const char* str, SizeType len, bool copy) override
method StartObject (line 167) | bool StartObject() override
method EndObject (line 174) | bool EndObject(SizeType len) override
method StartArray (line 181) | bool StartArray() override
method EndArray (line 188) | bool EndArray(SizeType len) override
method has_error (line 195) | bool has_error() const override { return internal_handler && interna...
method reap_error (line 197) | bool reap_error(ErrorStack& stk) override
method type_name (line 202) | std::string type_name() const override
type staticjson (line 20) | namespace staticjson
class Handler<optional<T>> (line 39) | class Handler<optional<T>> : public BaseHandler
method Handler (line 50) | explicit Handler(optional<T>* value) : m_value(value) {}
method initialize (line 53) | void initialize()
method reset (line 62) | void reset() override
method postcheck (line 69) | bool postcheck(bool success)
method Null (line 77) | bool Null() override
method write (line 92) | bool write(IHandler* out) const override
method generate_schema (line 105) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
method Bool (line 119) | bool Bool(bool b) override
method Int (line 125) | bool Int(int i) override
method Uint (line 131) | bool Uint(unsigned i) override
method Int64 (line 137) | bool Int64(std::int64_t i) override
method Uint64 (line 143) | bool Uint64(std::uint64_t i) override
method Double (line 149) | bool Double(double i) override
method String (line 155) | bool String(const char* str, SizeType len, bool copy) override
method Key (line 161) | bool Key(const char* str, SizeType len, bool copy) override
method StartObject (line 167) | bool StartObject() override
method EndObject (line 174) | bool EndObject(SizeType len) override
method StartArray (line 181) | bool StartArray() override
method EndArray (line 188) | bool EndArray(SizeType len) override
method has_error (line 195) | bool has_error() const override { return internal_handler && interna...
method reap_error (line 197) | bool reap_error(ErrorStack& stk) override
method type_name (line 202) | std::string type_name() const override
type staticjson (line 35) | namespace staticjson
class Handler<optional<T>> (line 39) | class Handler<optional<T>> : public BaseHandler
method Handler (line 50) | explicit Handler(optional<T>* value) : m_value(value) {}
method initialize (line 53) | void initialize()
method reset (line 62) | void reset() override
method postcheck (line 69) | bool postcheck(bool success)
method Null (line 77) | bool Null() override
method write (line 92) | bool write(IHandler* out) const override
method generate_schema (line 105) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
method Bool (line 119) | bool Bool(bool b) override
method Int (line 125) | bool Int(int i) override
method Uint (line 131) | bool Uint(unsigned i) override
method Int64 (line 137) | bool Int64(std::int64_t i) override
method Uint64 (line 143) | bool Uint64(std::uint64_t i) override
method Double (line 149) | bool Double(double i) override
method String (line 155) | bool String(const char* str, SizeType len, bool copy) override
method Key (line 161) | bool Key(const char* str, SizeType len, bool copy) override
method StartObject (line 167) | bool StartObject() override
method EndObject (line 174) | bool EndObject(SizeType len) override
method StartArray (line 181) | bool StartArray() override
method EndArray (line 188) | bool EndArray(SizeType len) override
method has_error (line 195) | bool has_error() const override { return internal_handler && interna...
method reap_error (line 197) | bool reap_error(ErrorStack& stk) override
method type_name (line 202) | std::string type_name() const override
FILE: include/staticjson/primitive_types.hpp
type staticjson (line 8) | namespace staticjson
class IntegerHandler (line 12) | class IntegerHandler : public BaseHandler
method is_out_of_range (line 20) | static constexpr typename std::enable_if<std::is_integral<AnotherInt...
method is_out_of_range (line 39) | static constexpr typename std::enable_if<std::is_floating_point<Floa...
method receive (line 46) | bool receive(ReceiveNumType r, const char* actual_type)
method IntegerHandler (line 56) | explicit IntegerHandler(IntType* value) : m_value(value) {}
method Int (line 58) | bool Int(int i) override { return receive(i, "int"); }
method Uint (line 60) | bool Uint(unsigned i) override { return receive(i, "unsigned int"); }
method Int64 (line 62) | bool Int64(std::int64_t i) override { return receive(i, "std::int64_...
method Uint64 (line 64) | bool Uint64(std::uint64_t i) override { return receive(i, "std::uint...
method Double (line 66) | bool Double(double d) override { return receive(d, "double"); }
method write (line 68) | bool write(IHandler* output) const override
method generate_schema (line 80) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
class Handler<std::nullptr_t> (line 101) | class Handler<std::nullptr_t> : public BaseHandler
method Handler (line 104) | explicit Handler(std::nullptr_t*) {}
method Null (line 106) | bool Null() override
method type_name (line 112) | std::string type_name() const override { return "null"; }
method write (line 114) | bool write(IHandler* output) const override { return output->Null(); }
method generate_schema (line 116) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
class Handler<bool> (line 124) | class Handler<bool> : public BaseHandler
method Handler (line 130) | explicit Handler(bool* value) : m_value(value) {}
method Bool (line 132) | bool Bool(bool v) override
method type_name (line 139) | std::string type_name() const override { return "bool"; }
method write (line 141) | bool write(IHandler* output) const override { return output->Bool(*m...
method generate_schema (line 143) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
class Handler<int> (line 151) | class Handler<int> : public IntegerHandler<int>
method Handler (line 154) | explicit Handler(int* i) : IntegerHandler<int>(i) {}
method type_name (line 156) | std::string type_name() const override { return "int"; }
method write (line 158) | bool write(IHandler* output) const override { return output->Int(*m_...
class Handler<unsigned int> (line 162) | class Handler<unsigned int> : public IntegerHandler<unsigned int>
method Handler (line 165) | explicit Handler(unsigned* i) : IntegerHandler<unsigned int>(i) {}
method type_name (line 167) | std::string type_name() const override { return "unsigned int"; }
method write (line 169) | bool write(IHandler* output) const override { return output->Uint(*m...
class Handler<long> (line 173) | class Handler<long> : public IntegerHandler<long>
method Handler (line 176) | explicit Handler(long* i) : IntegerHandler<long>(i) {}
method type_name (line 178) | std::string type_name() const override { return "long"; }
class Handler<unsigned long> (line 182) | class Handler<unsigned long> : public IntegerHandler<unsigned long>
method Handler (line 185) | explicit Handler(unsigned long* i) : IntegerHandler<unsigned long>(i...
method type_name (line 187) | std::string type_name() const override { return "unsigned long"; }
class Handler<long long> (line 191) | class Handler<long long> : public IntegerHandler<long long>
method Handler (line 194) | explicit Handler(long long* i) : IntegerHandler<long long>(i) {}
method type_name (line 196) | std::string type_name() const override { return "long long"; }
class Handler<unsigned long long> (line 200) | class Handler<unsigned long long> : public IntegerHandler<unsigned lon...
method Handler (line 203) | explicit Handler(unsigned long long* i) : IntegerHandler<unsigned lo...
method type_name (line 205) | std::string type_name() const override { return "unsigned long long"; }
class Handler<char> (line 210) | class Handler<char> : public BaseHandler
method Handler (line 216) | explicit Handler(char* i) : m_value(i) {}
method type_name (line 218) | std::string type_name() const override { return "bool"; }
method Bool (line 220) | bool Bool(bool v) override
method write (line 227) | bool write(IHandler* out) const override { return out->Bool(*m_value...
method generate_schema (line 229) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
class Handler<double> (line 237) | class Handler<double> : public BaseHandler
method Handler (line 243) | explicit Handler(double* v) : m_value(v) {}
method Int (line 245) | bool Int(int i) override
method Uint (line 252) | bool Uint(unsigned i) override
method Int64 (line 259) | bool Int64(std::int64_t i) override
method Uint64 (line 268) | bool Uint64(std::uint64_t i) override
method Double (line 277) | bool Double(double d) override
method type_name (line 284) | std::string type_name() const override { return "double"; }
method write (line 286) | bool write(IHandler* out) const override { return out->Double(*m_val...
method generate_schema (line 288) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
class Handler<float> (line 296) | class Handler<float> : public BaseHandler
method Handler (line 302) | explicit Handler(float* v) : m_value(v) {}
method Int (line 304) | bool Int(int i) override
method Uint (line 313) | bool Uint(unsigned i) override
method Int64 (line 322) | bool Int64(std::int64_t i) override
method Uint64 (line 331) | bool Uint64(std::uint64_t i) override
method Double (line 340) | bool Double(double d) override
method type_name (line 347) | std::string type_name() const override { return "float"; }
method write (line 349) | bool write(IHandler* out) const override { return out->Double(*m_val...
method generate_schema (line 351) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
class Handler<std::string> (line 359) | class Handler<std::string> : public BaseHandler
method Handler (line 365) | explicit Handler(std::string* v) : m_value(v) {}
method String (line 367) | bool String(const char* str, SizeType length, bool) override
method type_name (line 374) | std::string type_name() const override { return "string"; }
method write (line 376) | bool write(IHandler* out) const override
method generate_schema (line 381) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
FILE: include/staticjson/stl_types.hpp
type staticjson (line 13) | namespace staticjson
class ArrayHandler (line 16) | class ArrayHandler : public BaseHandler
method set_element_error (line 28) | void set_element_error() { the_error.reset(new error::ArrayElementEr...
method precheck (line 30) | bool precheck(const char* type)
method postcheck (line 40) | bool postcheck(bool success)
method reset (line 56) | void reset() override
method ArrayHandler (line 64) | explicit ArrayHandler(ArrayType* value) : element(), internal(&eleme...
method Null (line 66) | bool Null() override { return precheck("null") && postcheck(internal...
method Bool (line 68) | bool Bool(bool b) override { return precheck("bool") && postcheck(in...
method Int (line 70) | bool Int(int i) override { return precheck("int") && postcheck(inter...
method Uint (line 72) | bool Uint(unsigned i) override { return precheck("unsigned") && post...
method Int64 (line 74) | bool Int64(std::int64_t i) override
method Uint64 (line 79) | bool Uint64(std::uint64_t i) override
method Double (line 84) | bool Double(double d) override { return precheck("double") && postch...
method String (line 86) | bool String(const char* str, SizeType length, bool copy) override
method Key (line 91) | bool Key(const char* str, SizeType length, bool copy) override
method StartObject (line 96) | bool StartObject() override { return precheck("object") && postcheck...
method EndObject (line 98) | bool EndObject(SizeType length) override
method StartArray (line 103) | bool StartArray() override
method EndArray (line 113) | bool EndArray(SizeType length) override
method reap_error (line 125) | bool reap_error(ErrorStack& stk) override
method write (line 134) | bool write(IHandler* output) const override
method generate_schema (line 147) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
class Handler<std::vector<T>> (line 160) | class Handler<std::vector<T>> : public ArrayHandler<std::vector<T>>
method Handler (line 163) | explicit Handler(std::vector<T>* value) : ArrayHandler<std::vector<T...
method type_name (line 165) | std::string type_name() const override
class Handler<std::deque<T>> (line 172) | class Handler<std::deque<T>> : public ArrayHandler<std::deque<T>>
method Handler (line 175) | explicit Handler(std::deque<T>* value) : ArrayHandler<std::deque<T>>...
method type_name (line 177) | std::string type_name() const override
class Handler<std::list<T>> (line 184) | class Handler<std::list<T>> : public ArrayHandler<std::list<T>>
method Handler (line 187) | explicit Handler(std::list<T>* value) : ArrayHandler<std::list<T>>(v...
method type_name (line 189) | std::string type_name() const override
class Handler<std::array<T, N>> (line 196) | class Handler<std::array<T, N>> : public BaseHandler
method set_element_error (line 206) | void set_element_error() { the_error.reset(new error::ArrayElementEr...
method set_length_error (line 208) | void set_length_error() { the_error.reset(new error::ArrayLengthMism...
method precheck (line 210) | bool precheck(const char* type)
method postcheck (line 220) | bool postcheck(bool success)
method reset (line 242) | void reset() override
method Handler (line 251) | explicit Handler(std::array<T, N>* value) : element(), internal(&ele...
method Null (line 253) | bool Null() override { return precheck("null") && postcheck(internal...
method Bool (line 255) | bool Bool(bool b) override { return precheck("bool") && postcheck(in...
method Int (line 257) | bool Int(int i) override { return precheck("int") && postcheck(inter...
method Uint (line 259) | bool Uint(unsigned i) override { return precheck("unsigned") && post...
method Int64 (line 261) | bool Int64(std::int64_t i) override
method Uint64 (line 266) | bool Uint64(std::uint64_t i) override
method Double (line 271) | bool Double(double d) override { return precheck("double") && postch...
method String (line 273) | bool String(const char* str, SizeType length, bool copy) override
method Key (line 278) | bool Key(const char* str, SizeType length, bool copy) override
method StartObject (line 283) | bool StartObject() override { return precheck("object") && postcheck...
method EndObject (line 285) | bool EndObject(SizeType length) override
method StartArray (line 290) | bool StartArray() override
method EndArray (line 298) | bool EndArray(SizeType length) override
method reap_error (line 314) | bool reap_error(ErrorStack& stk) override
method write (line 323) | bool write(IHandler* output) const override
method generate_schema (line 336) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
method type_name (line 347) | std::string type_name() const override
class PointerHandler (line 354) | class PointerHandler : public BaseHandler
method PointerHandler (line 365) | explicit PointerHandler(PointerType* value) : m_value(value) {}
method initialize (line 367) | void initialize()
method reset (line 376) | void reset() override
method postcheck (line 383) | bool postcheck(bool success)
method Null (line 391) | bool Null() override
method write (line 406) | bool write(IHandler* out) const override
method generate_schema (line 419) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
method Bool (line 433) | bool Bool(bool b) override
method Int (line 439) | bool Int(int i) override
method Uint (line 445) | bool Uint(unsigned i) override
method Int64 (line 451) | bool Int64(std::int64_t i) override
method Uint64 (line 457) | bool Uint64(std::uint64_t i) override
method Double (line 463) | bool Double(double i) override
method String (line 469) | bool String(const char* str, SizeType len, bool copy) override
method Key (line 475) | bool Key(const char* str, SizeType len, bool copy) override
method StartObject (line 481) | bool StartObject() override
method EndObject (line 488) | bool EndObject(SizeType len) override
method StartArray (line 495) | bool StartArray() override
method EndArray (line 502) | bool EndArray(SizeType len) override
method has_error (line 509) | bool has_error() const override { return internal_handler && interna...
method reap_error (line 511) | bool reap_error(ErrorStack& stk) override
class Handler<std::unique_ptr<T, Deleter>> (line 518) | class Handler<std::unique_ptr<T, Deleter>> : public PointerHandler<std...
method Handler (line 521) | explicit Handler(std::unique_ptr<T, Deleter>* value)
method type_name (line 526) | std::string type_name() const override
class Handler<std::shared_ptr<T>> (line 537) | class Handler<std::shared_ptr<T>> : public PointerHandler<std::shared_...
method Handler (line 540) | explicit Handler(std::shared_ptr<T>* value) : PointerHandler<std::sh...
method type_name (line 542) | std::string type_name() const override
class MapHandler (line 553) | class MapHandler : public BaseHandler
method reset (line 566) | void reset() override
method precheck (line 574) | bool precheck(const char* type)
method postcheck (line 584) | bool postcheck(bool success)
method MapHandler (line 603) | explicit MapHandler(MapType* value) : element(), internal_handler(&e...
method Null (line 605) | bool Null() override { return precheck("null") && postcheck(internal...
method Bool (line 607) | bool Bool(bool b) override { return precheck("bool") && postcheck(in...
method Int (line 609) | bool Int(int i) override { return precheck("int") && postcheck(inter...
method Uint (line 611) | bool Uint(unsigned i) override
method Int64 (line 616) | bool Int64(std::int64_t i) override
method Uint64 (line 621) | bool Uint64(std::uint64_t i) override
method Double (line 626) | bool Double(double d) override
method String (line 631) | bool String(const char* str, SizeType length, bool copy) override
method Key (line 636) | bool Key(const char* str, SizeType length, bool copy) override
method StartArray (line 645) | bool StartArray() override
method EndArray (line 650) | bool EndArray(SizeType length) override
method StartObject (line 655) | bool StartObject() override
method EndObject (line 665) | bool EndObject(SizeType length) override
method reap_error (line 674) | bool reap_error(ErrorStack& errs) override
method write (line 684) | bool write(IHandler* out) const override
method generate_schema (line 699) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
class Handler<std::unordered_map<std::string, T, Hash, Equal>> (line 713) | class Handler<std::unordered_map<std::string, T, Hash, Equal>>
method Handler (line 717) | explicit Handler(std::unordered_map<std::string, T, Hash, Equal>* va...
method type_name (line 722) | std::string type_name() const override
class Handler<std::map<std::string, T, Hash, Equal>> (line 729) | class Handler<std::map<std::string, T, Hash, Equal>>
method Handler (line 733) | explicit Handler(std::map<std::string, T, Hash, Equal>* value)
method type_name (line 738) | std::string type_name() const override
class Handler<std::unordered_multimap<std::string, T, Hash, Equal>> (line 745) | class Handler<std::unordered_multimap<std::string, T, Hash, Equal>>
method Handler (line 749) | explicit Handler(std::unordered_multimap<std::string, T, Hash, Equal...
method type_name (line 754) | std::string type_name() const override
class Handler<std::multimap<std::string, T, Hash, Equal>> (line 761) | class Handler<std::multimap<std::string, T, Hash, Equal>>
method Handler (line 765) | explicit Handler(std::multimap<std::string, T, Hash, Equal>* value)
method type_name (line 770) | std::string type_name() const override
class TupleHander (line 777) | class TupleHander : public BaseHandler
method postcheck (line 784) | bool postcheck(bool success)
method reset (line 799) | void reset() override
method Null (line 808) | bool Null() override
method Bool (line 815) | bool Bool(bool b) override
method Int (line 822) | bool Int(int i) override
method Uint (line 829) | bool Uint(unsigned i) override
method Int64 (line 836) | bool Int64(std::int64_t i) override
method Uint64 (line 843) | bool Uint64(std::uint64_t i) override
method Double (line 850) | bool Double(double d) override
method String (line 857) | bool String(const char* str, SizeType length, bool copy) override
method Key (line 864) | bool Key(const char* str, SizeType length, bool copy) override
method StartArray (line 871) | bool StartArray() override
method EndArray (line 882) | bool EndArray(SizeType length) override
method StartObject (line 894) | bool StartObject() override
method EndObject (line 901) | bool EndObject(SizeType length) override
method reap_error (line 908) | bool reap_error(ErrorStack& errs) override
method write (line 919) | bool write(IHandler* out) const override
method generate_schema (line 931) | void generate_schema(Value& output, MemoryPoolAllocator& alloc) cons...
type nonpublic (line 946) | namespace nonpublic
type TupleIniter (line 949) | struct TupleIniter
type TupleIniter<N, N, Tuple> (line 960) | struct TupleIniter<N, N, Tuple>
class Handler<std::tuple<Ts...>> (line 971) | class Handler<std::tuple<Ts...>> : public TupleHander<std::tuple_size<st...
method Handler (line 977) | explicit Handler(std::tuple<Ts...>* t)
method type_name (line 983) | std::string type_name() const override
FILE: src/staticjson.cpp
type staticjson (line 18) | namespace staticjson
function quote (line 36) | inline std::string quote(const std::string& str)
function stringprintf (line 164) | static std::string stringprintf(const char* format, ...)
type nonpublic (line 679) | namespace nonpublic
class IHandlerAdapter (line 682) | class IHandlerAdapter : public IHandler
method IHandlerAdapter (line 688) | explicit IHandlerAdapter(T* t) : t(t) {}
method Null (line 690) | virtual bool Null() override { return t->Null(); }
method Bool (line 692) | virtual bool Bool(bool v) override { return t->Bool(v); }
method Int (line 694) | virtual bool Int(int v) override { return t->Int(v); }
method Uint (line 696) | virtual bool Uint(unsigned v) override { return t->Uint(v); }
method Int64 (line 698) | virtual bool Int64(std::int64_t v) override { return t->Int64(v); }
method Uint64 (line 700) | virtual bool Uint64(std::uint64_t v) override { return t->Uint64(v...
method Double (line 702) | virtual bool Double(double v) override { return t->Double(v); }
method String (line 704) | virtual bool String(const char* str, SizeType sz, bool copy) override
method StartObject (line 709) | virtual bool StartObject() override { return t->StartObject(); }
method Key (line 711) | virtual bool Key(const char* str, SizeType sz, bool copy) override
method EndObject (line 716) | virtual bool EndObject(SizeType sz) override { return t->EndObject...
method StartArray (line 718) | virtual bool StartArray() override { return t->StartArray(); }
method EndArray (line 720) | virtual bool EndArray(SizeType sz) override { return t->EndArray(s...
method prepare_for_reuse (line 722) | virtual void prepare_for_reuse() override { std::terminate(); }
function read_json (line 726) | static bool read_json(InputStream& is, BaseHandler* h, ParseStatus* ...
function parse_json_string (line 738) | bool parse_json_string(const char* str, BaseHandler* handler, ParseS...
function parse_json_file (line 744) | bool parse_json_file(std::FILE* fp, BaseHandler* handler, ParseStatu...
type StringOutputStream (line 753) | struct StringOutputStream : private NonMobile
method Put (line 759) | void Put(char c) { str->push_back(c); }
method Flush (line 761) | void Flush() {}
function serialize_json_string (line 764) | std::string serialize_json_string(const BaseHandler* handler)
function serialize_json_file (line 775) | bool serialize_json_file(std::FILE* fp, const BaseHandler* handler)
function serialize_pretty_json_string (line 786) | std::string serialize_pretty_json_string(const BaseHandler* handler)
function serialize_pretty_json_file (line 798) | bool serialize_pretty_json_file(std::FILE* fp, const BaseHandler* ha...
function write_value (line 814) | bool write_value(const Value& v, BaseHandler* out, ParseStatus* status)
function read_value (line 828) | bool
function Value (line 870) | Value& JSONHandler::stack_top()
function GlobalConfig (line 1014) | GlobalConfig* GlobalConfig::getInstance() noexcept
type mempool (line 1020) | namespace mempool
function throw_bad_alloc (line 1022) | [[noreturn]] void throw_bad_alloc()
FILE: test/myarray.hpp
class Array (line 7) | class Array
method Array (line 14) | explicit Array() : m_data(nullptr), m_size(0) {}
method Array (line 15) | explicit Array(size_t size) : m_size(size) { m_data = new T[size]; }
method Array (line 17) | Array(Array&& that) noexcept
method Array (line 24) | Array& operator=(Array&& that) noexcept
method T (line 30) | const T& operator[](size_t i) const { return m_data[i]; }
method T (line 31) | T& operator[](size_t i) { return m_data[i]; }
method size (line 32) | size_t size() const { return m_size; }
method T (line 33) | const T& back() const { return m_data[m_size - 1]; }
method T (line 34) | T& back() { return m_data[m_size - 1]; }
method T (line 35) | const T& front() const { return m_data[0]; }
method T (line 36) | T& front() { return m_data[0]; }
method empty (line 37) | bool empty() const { return m_size == 0; }
method clear (line 38) | void clear()
type staticjson (line 46) | namespace staticjson
type Converter<Array<T>> (line 49) | struct Converter<Array<T>>
method from_shadow (line 53) | static std::unique_ptr<ErrorBase> from_shadow(const shadow_type& sha...
method to_shadow (line 63) | static void to_shadow(const Array<T>& value, shadow_type& shadow)
FILE: test/test_autojsoncxx.cpp
type config (line 40) | namespace config
type event (line 52) | namespace event
type config (line 50) | namespace config
type event (line 52) | namespace event
function read_all (line 71) | static std::string read_all(const std::string& file_name)
function Date (line 79) | static Date create_date(int year, int month, int day)
FILE: test/test_basic.cpp
type MyObject (line 7) | struct MyObject
method staticjson_init (line 11) | void staticjson_init(ObjectHandler* h)
FILE: test/test_example.cpp
function builtin_test (line 6) | int builtin_test()
FILE: test/test_instantiation.cpp
function instantiate_all_types (line 10) | void instantiate_all_types()
FILE: test/test_integration.cpp
type Initializer (line 31) | struct Initializer
method Initializer (line 35) | Initializer()
type CalendarType (line 63) | enum class CalendarType
type Date (line 77) | struct Date
method Date (line 82) | Date() : year(0), month(0), day(0), type(CalendarType::Gregorian) {}
type staticjson (line 85) | namespace staticjson
function init (line 87) | void init(Date* d, ObjectHandler* h)
class Handler<User> (line 141) | class Handler<User> : public ObjectHandler
method Handler (line 144) | explicit Handler(User* user)
method type_name (line 160) | std::string type_name() const override { return "User"; }
type BlockEvent (line 97) | struct BlockEvent
method staticjson_init (line 106) | void staticjson_init(ObjectHandler* h)
type User (line 119) | struct User
type staticjson (line 138) | namespace staticjson
function init (line 87) | void init(Date* d, ObjectHandler* h)
class Handler<User> (line 141) | class Handler<User> : public ObjectHandler
method Handler (line 144) | explicit Handler(User* user)
method type_name (line 160) | std::string type_name() const override { return "User"; }
function read_all (line 189) | inline std::string read_all(const std::string& file_name)
function Date (line 205) | inline Date create_date(int year, int month, int day)
method Date (line 82) | Date() : year(0), month(0), day(0), type(CalendarType::Gregorian) {}
function check_first_user (line 214) | void check_first_user(const User& u)
function check_second_user (line 260) | void check_second_user(const User& u)
function check_array_of_user (line 270) | void check_array_of_user(const ArrayOfUsers& users)
function check_array_of_user (line 278) | void check_array_of_user(const Document& users)
function is_valid_json (line 624) | static bool is_valid_json(const std::string& filename, rapidjson::Schema...
FILE: test/test_memory_usage.cpp
type Simple (line 11) | struct Simple
method staticjson_init (line 15) | void staticjson_init(ObjectHandler* h) { h->add_property("floats", &fl...
type Struct (line 18) | struct Struct
method staticjson_init (line 24) | void staticjson_init(ObjectHandler* h)
Condensed preview — 65 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (251K chars).
[
{
"path": ".cmake-format.py",
"chars": 8656,
"preview": "# ----------------------------------\r\n# Options affecting listfile parsing\r\n# ----------------------------------\r\nwith s"
},
{
"path": ".github/workflows/ccpp.yaml",
"chars": 961,
"preview": "name: C/C++ CI\n\non: [push, pull_request]\n\nenv:\n VERBOSE: 1\n\njobs:\n build_matrix:\n strategy:\n matrix:\n c"
},
{
"path": ".gitignore",
"chars": 452,
"preview": ".DS_Store\n._*\nxcode/\n*.backup\n# Prerequisites\n*.d\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*"
},
{
"path": ".travis.yml",
"chars": 113,
"preview": "language: cpp\nsudo: required\ndist: trusty\nscript: \"sudo apt-get install -y cmake && cmake . && make && ctest -V\"\n"
},
{
"path": "CMakeLists.txt",
"chars": 2503,
"preview": "cmake_minimum_required(VERSION 3.0)\nproject(StaticJSON)\n\noption(STATICJSON_ENABLE_TEST \"Enable building test for StaticJ"
},
{
"path": "LICENSE",
"chars": 1100,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Siyuan Ren (netheril96@gmail.com)\n\nPermission is hereby granted, free of charg"
},
{
"path": "README.md",
"chars": 7760,
"preview": "# StaticJSON\n\nFast, direct and static typed parsing of JSON with C++.\n\n## Overview\n\nJSON is a popular format for data ex"
},
{
"path": "_clang-format",
"chars": 2004,
"preview": "---\nLanguage: Cpp\n# BasedOnStyle: WebKit\nAccessModifierOffset: -4\nAlignAfterOpenBracket: true\nAlignEscapedNewlin"
},
{
"path": "autojsoncxx/autojsoncxx.hpp",
"chars": 1964,
"preview": "#pragma once\n\n#include <cstdio>\n#include <staticjson/staticjson.hpp>\n#include <string>\n\nnamespace autojsoncxx\n{\nusing Pa"
},
{
"path": "autojsoncxx/autojsoncxx.py",
"chars": 10630,
"preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n# The MIT License (MIT)\n#\n# Copyright (c) 2014 Siyuan Ren (netheril96@gma"
},
{
"path": "autojsoncxx/examples/failure/duplicate_key.json",
"chars": 1764,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "autojsoncxx/examples/failure/duplicate_key_user.json",
"chars": 1595,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "autojsoncxx/examples/failure/hard.json",
"chars": 1280,
"preview": "[{\"serial_number\": 90049710466114, \"details\": \"unknown\"}, -65535, null, 2.718281828459045, {\"Second\": {\"ID\": 13478355757"
},
{
"path": "autojsoncxx/examples/failure/integer_string.json",
"chars": 1573,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "autojsoncxx/examples/failure/map_element_mismatch.json",
"chars": 1603,
"preview": "{\n\"First\": {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n "
},
{
"path": "autojsoncxx/examples/failure/missing_required.json",
"chars": 1397,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "autojsoncxx/examples/failure/null_in_key.json",
"chars": 1621,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "autojsoncxx/examples/failure/out_of_range.json",
"chars": 1589,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "autojsoncxx/examples/failure/single_object.json",
"chars": 544,
"preview": "\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \"y"
},
{
"path": "autojsoncxx/examples/failure/unknown_field.json",
"chars": 1514,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "autojsoncxx/examples/success/hard.json",
"chars": 1277,
"preview": "[{\"serial_number\": 90049710466114, \"details\": \"unknown\"}, -65535, null, 2.718281828459045, {\"Second\": {\"ID\": 13478355757"
},
{
"path": "autojsoncxx/examples/success/user_array.json",
"chars": 1573,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "autojsoncxx/examples/success/user_array_compact.json",
"chars": 841,
"preview": "[{\"ID\":7947402710862746952,\"nickname\":\"bigger than bigger\",\"birthday\":{\"year\":1984,\"month\":9,\"day\":2},\"block_event\":{\"se"
},
{
"path": "autojsoncxx/examples/success/user_map.json",
"chars": 1587,
"preview": "{\n\"First\": {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n "
},
{
"path": "autojsoncxx/userdef.hpp",
"chars": 3503,
"preview": "#pragma once\n\nnamespace config\n{\nstruct Date\n{\n int year;\n int month;\n int day;\n\n explicit Date() : year(), "
},
{
"path": "autojsoncxx/userdef.json",
"chars": 1249,
"preview": "[\n{\n \"name\": \"Date\",\n \"namespace\": \"config\",\n \"parse_mode\": \"strict\",\n \"members\": [\n [\"int\", \"year\", "
},
{
"path": "cmake/staticjson-config.cmake.in",
"chars": 194,
"preview": "@PACKAGE_INIT@\ninclude(CMakeFindDependencyMacro)\nfind_dependency(rapidjson CONFIG)\n\nif(NOT TARGET staticjson::staticjson"
},
{
"path": "examples/failure/duplicate_key.json",
"chars": 1764,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "examples/failure/duplicate_key_user.json",
"chars": 1595,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "examples/failure/hard.json",
"chars": 1280,
"preview": "[{\"serial_number\": 90049710466114, \"details\": \"unknown\"}, -65535, null, 2.718281828459045, {\"Second\": {\"ID\": 13478355757"
},
{
"path": "examples/failure/integer_string.json",
"chars": 1573,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "examples/failure/invalid_enum.json",
"chars": 2442,
"preview": "{\n\"First\": {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n "
},
{
"path": "examples/failure/map_element_mismatch.json",
"chars": 1603,
"preview": "{\n\"First\": {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n "
},
{
"path": "examples/failure/missing_required.json",
"chars": 1397,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "examples/failure/null_in_key.json",
"chars": 1621,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "examples/failure/out_of_range.json",
"chars": 1589,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "examples/failure/single_object.json",
"chars": 544,
"preview": "\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \"y"
},
{
"path": "examples/failure/tensor_length_error.json",
"chars": 11,
"preview": "[\n []\n]\n"
},
{
"path": "examples/failure/tensor_type_mismatch.json",
"chars": 18,
"preview": "[\n\t\t[\"1\", 2, 3]\n]\n"
},
{
"path": "examples/failure/unknown_field.json",
"chars": 1514,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "examples/success/hard.json",
"chars": 1277,
"preview": "[{\"serial_number\": 90049710466114, \"details\": \"unknown\"}, -65535, null, 2.718281828459045, {\"Second\": {\"ID\": 13478355757"
},
{
"path": "examples/success/tensor.json",
"chars": 172,
"preview": "[\n\t\t[\n\t\t\t\t[1, 2, 3],\n\t\t\t\t[4, 5, 6],\n\t\t\t\t[7, 8, 0]\n\t\t],\n\t\t[\n\t\t\t\t[1.0, 2.0],\n\t\t\t\t[3.0, 4.0],\n\t\t\t\t[5.0, 6.0]\n\t\t],\n\t\t[\n\t\t\t\t["
},
{
"path": "examples/success/user_array.json",
"chars": 3027,
"preview": "[\n {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n \""
},
{
"path": "examples/success/user_array_compact.json",
"chars": 841,
"preview": "[{\"ID\":7947402710862746952,\"nickname\":\"bigger than bigger\",\"birthday\":{\"year\":1984,\"month\":9,\"day\":2},\"block_event\":{\"se"
},
{
"path": "examples/success/user_map.json",
"chars": 2406,
"preview": "{\n\"First\": {\n \"ID\": 7947402710862746952,\n \"nickname\": \"bigger than bigger\",\n \"birthday\": {\n "
},
{
"path": "format.sh",
"chars": 190,
"preview": "#!/bin/sh\ncd $(dirname $0)\nGLOBIGNORE=\"include/staticjson/optional_support.hpp\"\nclang-format -i --style=File autojsoncxx"
},
{
"path": "include/staticjson/basic.hpp",
"chars": 15398,
"preview": "#pragma once\n\n#include <rapidjson/document.h>\n#include <staticjson/error.hpp>\n\n#include <climits>\n#include <cstddef>\n#in"
},
{
"path": "include/staticjson/document.hpp",
"chars": 2605,
"preview": "#pragma once\n#include <staticjson/basic.hpp>\n\n#include <rapidjson/document.h>\n\n#include <vector>\n\nnamespace staticjson\n{"
},
{
"path": "include/staticjson/enum.hpp",
"chars": 3512,
"preview": "#pragma once\n\n#include <staticjson/primitive_types.hpp>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespac"
},
{
"path": "include/staticjson/error.hpp",
"chars": 10228,
"preview": "#pragma once\n\n#include <algorithm>\n#include <cstddef>\n#include <iterator>\n#include <string>\n#include <utility>\n#include "
},
{
"path": "include/staticjson/forward_declarations.hpp",
"chars": 164,
"preview": "#pragma once\n\nnamespace staticjson\n{\ntypedef unsigned int SizeType;\n\nclass IHandler;\n\nclass BaseHandler;\n\nclass ObjectHa"
},
{
"path": "include/staticjson/io.hpp",
"chars": 3193,
"preview": "#pragma once\n\n#include <staticjson/basic.hpp>\n\n#include <cstdio>\n#include <string>\n\nnamespace staticjson\n{\n\nnamespace no"
},
{
"path": "include/staticjson/optional_support.hpp",
"chars": 4650,
"preview": "#pragma once\n\n#include \"stl_types.hpp\"\n\n#ifdef __has_include\n#if __has_include(<optional>)\n#include <optional>\n\nnamespac"
},
{
"path": "include/staticjson/primitive_types.hpp",
"chars": 10563,
"preview": "#pragma once\n#include <staticjson/basic.hpp>\n\n#include <limits>\n#include <string>\n#include <type_traits>\n\nnamespace stat"
},
{
"path": "include/staticjson/staticjson.hpp",
"chars": 218,
"preview": "#pragma once\n#include <staticjson/basic.hpp>\n#include <staticjson/document.hpp>\n#include <staticjson/enum.hpp>\n#include "
},
{
"path": "include/staticjson/stl_types.hpp",
"chars": 26018,
"preview": "#pragma once\n#include <staticjson/basic.hpp>\n\n#include <array>\n#include <deque>\n#include <list>\n#include <map>\n#include "
},
{
"path": "src/staticjson.cpp",
"chars": 26222,
"preview": "#include <staticjson/document.hpp>\n#include <staticjson/staticjson.hpp>\n\n#include <rapidjson/error/en.h>\n#include <rapid"
},
{
"path": "test/myarray.hpp",
"chars": 1796,
"preview": "#include <deque>\n#include <staticjson/staticjson.hpp>\n\n// This class is used to test custom conversion functions in Stat"
},
{
"path": "test/test_autojsoncxx.cpp",
"chars": 15745,
"preview": "// The MIT License (MIT)\n//\n// Copyright (c) 2014 Siyuan Ren (netheril96@gmail.com)\n//\n// Permission is hereby granted, "
},
{
"path": "test/test_basic.cpp",
"chars": 1192,
"preview": "#include <staticjson/staticjson.hpp>\n\n#include \"catch.hpp\"\n\nusing namespace staticjson;\n\nstruct MyObject\n{\n int i;\n\n "
},
{
"path": "test/test_example.cpp",
"chars": 784,
"preview": "#undef NDEBUG\n\n#include <cassert>\n#include <staticjson/staticjson.hpp>\n\nint builtin_test()\n{\n using namespace staticj"
},
{
"path": "test/test_instantiation.cpp",
"chars": 1142,
"preview": "#include <staticjson/document.hpp>\n#include <staticjson/staticjson.hpp>\n\n#define INSTANTIATE(type) "
},
{
"path": "test/test_integration.cpp",
"chars": 20971,
"preview": "#include \"catch.hpp\"\n#include \"myarray.hpp\"\n\n#include <staticjson/document.hpp>\n#include <staticjson/staticjson.hpp>\n\n#i"
},
{
"path": "test/test_memory_usage.cpp",
"chars": 1851,
"preview": "#include <staticjson/staticjson.hpp>\n\n#include \"catch.hpp\"\n\nusing namespace staticjson;\n\nnamespace\n{\nconst std::string C"
},
{
"path": "test/test_tensor.cpp",
"chars": 1286,
"preview": "#include <staticjson/staticjson.hpp>\n\n#include \"catch.hpp\"\n#include \"myarray.hpp\"\n\n#include <cerrno>\n#include <deque>\n#i"
}
]
About this extraction
This page contains the full source code of the netheril96/StaticJSON GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 65 files (227.8 KB), approximately 58.3k tokens, and a symbol index with 619 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.