Fuzz introspector
For issues and ideas: https://github.com/ossf/fuzz-introspector/issues

Project functions overview

The following table shows data about each function in the project. The functions included in this table correspond to all functions that exist in the executables of the fuzzers. As such, there may be functions that are from third-party libraries.

For further technical details on the meaning of columns in the below table, please see the Glossary .

Func name Functions filename Args Function call depth Reached by Fuzzers Runtime reached by Fuzzers Combined reached by Fuzzers Fuzzers runtime hit Func lines hit % I Count BB Count Cyclomatic complexity Functions reached Reached by functions Accumulated cyclomatic complexity Undiscovered complexity

Analyses and suggestions

Optimal target analysis

Remaining optimal interesting functions

The following table shows a list of functions that are optimal targets. Optimal targets are identified by finding the functions that in combination, yield a high code coverage.

Func name Functions filename Arg count Args Function depth hitcount instr count bb count cyclomatic complexity Reachable functions Incoming references total cyclomatic complexity Unreached complexity
ImGui::ColorPicker3 /src/tinygltf/examples/common/imgui/imgui.cpp 3 ['char*', 'float[]', 'ImGuiColorEditFlags'] 20 0 7 2 1 375 0 1200 1200
tinygltf::ParseImage /src/tinygltf/tiny_gltf.h 10 ['Image*', 'int', 'std::string*', 'std::string*', 'detail::json', 'bool', 'std::string', 'size_t', 'FsCallbacks*', 'URICallbacks*'] 15 0 73 21 22 285 0 1171 1161
GLEWAPIENTRY::glewIsSupported /src/tinygltf/examples/common/ThirdPartyLibs/Glew/glew.c 1 ['char*'] 1 0 2127 548 1063 4 0 1093 1093

Implementing fuzzers that target the above functions will improve reachability such that it becomes:

Functions statically reachable by fuzzers
8.0%
477 / 6005
Cyclomatic complexity statically reachable by fuzzers
20.0%
3696 / 18745

All functions overview

If you implement fuzzers for these functions, the status of all functions in the project will be:

Func name Functions filename Args Function call depth Reached by Fuzzers Runtime reached by Fuzzers Combined reached by Fuzzers Fuzzers runtime hit Func lines hit % I Count BB Count Cyclomatic complexity Functions reached Reached by functions Accumulated cyclomatic complexity Undiscovered complexity

Fuzz driver synthesis

New fuzzers

The below fuzzers are templates and suggestions for how to target the set of optimal functions above

imgui.cpp

Target file: /src/tinygltf/examples/common/imgui/imgui.cpp
Target functions: ImGui::ColorPicker3
#include "ada_fuzz_header.h"

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  af_safe_gb_init(data, size);

  /* target ImGui::ColorPicker3 */
  char *new_var0 = ada_safe_get_char_p();
  UNKNOWN_TYPE unknown_1;
  UNKNOWN_TYPE unknown_2;
  ImGui::ColorPicker3(new_var0, unknown_1, unknown_2);

  af_safe_gb_cleanup();
}

tiny_gltf.h

Target file: /src/tinygltf/tiny_gltf.h
Target functions: tinygltf::ParseImage
#include "ada_fuzz_header.h"

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  af_safe_gb_init(data, size);

  /* target tinygltf::ParseImage */
  UNKNOWN_TYPE unknown_3;
  int new_var4 = ada_safe_get_int();
  UNKNOWN_TYPE unknown_5;
  UNKNOWN_TYPE unknown_6;
  UNKNOWN_TYPE unknown_7;
  UNKNOWN_TYPE unknown_8;
  UNKNOWN_TYPE unknown_9;
  UNKNOWN_TYPE unknown_10;
  UNKNOWN_TYPE unknown_11;
  UNKNOWN_TYPE unknown_12;
  tinygltf::ParseImage(unknown_3, new_var4, unknown_5, unknown_6, unknown_7, unknown_8, unknown_9, unknown_10, unknown_11, unknown_12);

  af_safe_gb_cleanup();
}

glew.c

Target file: /src/tinygltf/examples/common/ThirdPartyLibs/Glew/glew.c
Target functions: GLEWAPIENTRY::glewIsSupported
#include "ada_fuzz_header.h"

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  af_safe_gb_init(data, size);

  /* target GLEWAPIENTRY::glewIsSupported */
  char *new_var13 = ada_safe_get_char_p();
  GLEWAPIENTRY::glewIsSupported(new_var13);

  af_safe_gb_cleanup();
}

Files and Directories in report

This section shows which files and directories are considered in this report. The main reason for showing this is fuzz introspector may include more code in the reasoning than is desired. This section helps identify if too many files/directories are included, e.g. third party code, which may be irrelevant for the threat model. In the event too much is included, fuzz introspector supports a configuration file that can exclude data from the report. See the following link for more information on how to create a config file: link

Files in report

Source file Reached by Covered by
/src/tinygltf/examples/common/glm/glm/detail/setup.hpp [] []
/src/tinygltf/examples/common/glm/glm/detail/_noise.hpp [] []
/src/tinygltf/examples/gltfutil/gltfuilconfig.h [] []
/src/tinygltf/examples/common/OpenGLWindow/Win32OpenGLWindow.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_type_vec4.cpp [] []
/src/tinygltf/examples/common/stb_image_write.h [] []
/src/tinygltf/examples/common/glm/test/external/gli/core/convert_func.hpp [] []
/src/tinygltf/examples/common/ThirdPartyLibs/Glew/CustomGL/glxew.h [] []
/src/tinygltf/examples/common/glm/glm/detail/_swizzle_func.hpp [] []
/src/tinygltf/examples/common/tinyexr.h ['tests/fuzzer/fuzz_gltf.cc'] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_matrix_query.cpp [] []
/src/tinygltf/examples/common/OpenGLWindow/MacOpenGLWindow.h [] []
/src/tinygltf/examples/raytrace/mesh.h [] []
/src/tinygltf/examples/raytrace/matrix.cc [] []
/src/tinygltf/stb_image_write.h [] []
/src/tinygltf/examples/common/ThirdPartyLibs/Glew/CustomGL/wglew.h [] []
/src/tinygltf/examples/raytrace/material.h [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_scalar_relational.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_type_precision.cpp [] []
/src/tinygltf/examples/common/glm/glm/detail/_vectorize.hpp [] []
/src/tinygltf/examples/common/glm/test/external/gli/dx.hpp [] []
/src/tinygltf/examples/basic/window.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_matrix_transform.cpp [] []
/src/tinygltf/examples/common/imgui/stb_image.h [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_constants.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_type_vec3.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_gradient_paint.cpp [] []
/src/tinygltf/examples/common/imgui/imgui_internal.h [] []
/src/tinygltf/examples/validator/src/json-schema.hpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_common.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_packing.cpp [] []
/src/tinygltf/examples/common/glm/glm/gtx/compatibility.hpp [] []
/src/tinygltf/examples/gltfutil/main.cc [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_log_base.cpp [] []
/src/tinygltf/examples/common/imgui/imgui.h [] []
/src/tinygltf/examples/common/glm/glm/gtx/vec_swizzle.hpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_bitfield.cpp [] []
/src/tinygltf/examples/common/OpenGLWindow/Win32Window.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_matrix.cpp [] []
/src/tinygltf/examples/common/glm/glm/detail/type_vec4.hpp [] []
/src/tinygltf/examples/raytrace/main.cc [] []
/src/tinygltf/stb_image.h ['tests/fuzzer/fuzz_gltf.cc'] []
/src/tinygltf/examples/validator/src/json.hpp ['tests/fuzzer/fuzz_gltf.cc'] []
/src/tinygltf/examples/glview/glview.cc [] []
/src/tinygltf/examples/common/OpenGLWindow/CommonWindowInterface.h [] []
/src/tinygltf/examples/common/ThirdPartyLibs/Glew/CustomGL/glew.h [] []
/src/tinygltf/examples/common/glm/test/core/core_type_aligned.cpp [] []
/src/tinygltf/examples/dxview/src/Viewer.cc [] []
/src/tinygltf/tests/tester.cc [] []
/src/tinygltf/examples/gltfutil/texture_dumper.cc [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_euler_angle.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_color_space.cpp [] []
/src/tinygltf/examples/dxview/src/dxview.cc [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_noise.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_component_wise.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_rotate_vector.cpp [] []
/src/tinygltf/examples/common/glm/test/external/gli/core/coord.hpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_epsilon.cpp [] []
/src/tinygltf/examples/common/ThirdPartyLibs/Glew/glew.c [] []
/src/tinygltf/examples/common/glm/glm/simd/exponential.h [] []
/src/tinygltf/examples/common/glm/test/external/gli/gl.hpp [] []
/src/tinygltf/examples/raytrace/render.h [] []
/src/tinygltf/examples/common/trackball.cc [] []
/src/tinygltf/examples/common/OpenGLWindow/X11OpenGLWindow.cpp [] []
/src/tinygltf/examples/validator/src/json-uri.cpp [] []
/src/tinygltf/examples/common/glm/test/external/gli/core/mipmaps_compute.hpp [] []
/src/tinygltf/examples/common/OpenGLWindow/Win32OpenGLWindow.h [] []
/src/tinygltf/examples/common/glm/test/core/core_type_length.cpp [] []
/src/tinygltf/examples/gltfutil/stb_image_write.h [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_fast_square_root.cpp [] []
/src/tinygltf/examples/common/imgui/imgui_impl_btgui.cpp [] []
/src/tinygltf/examples/raytrace/gltf-loader.cc [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_functions.cpp [] []
/src/tinygltf/examples/common/glm/glm/gtx/range.hpp [] []
/src/tinygltf/examples/raytrace/obj-loader.cc [] []
/src/tinygltf/tests/catch.hpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_string_cast.cpp [] []
/src/tinygltf/json.hpp ['tests/fuzzer/fuzz_gltf.cc'] []
/src/tinygltf/examples/common/nativefiledialog/src/nfd_win.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_packing.cpp [] []
/src/tinygltf/examples/common/glm/test/external/gli/core/workaround.hpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_noise.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_vector_query.cpp [] []
/src/tinygltf/examples/raytrace/render.cc [] []
/src/tinygltf/examples/common/nativefiledialog/src/nfd_common.c [] []
/src/tinygltf/examples/common/glm/glm/simd/matrix.h [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_intersect.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_geometric.cpp [] []
/src/tinygltf/examples/common/tiny_obj_loader.h [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_vector_angle.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_type_float.cpp [] []
/src/tinygltf/tests/fuzzer/fuzz_gltf.cc ['tests/fuzzer/fuzz_gltf.cc'] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_matrix_access.cpp [] []
/src/tinygltf/examples/common/glm/test/external/gli/format.hpp [] []
/src/tinygltf/examples/common/imgui/imgui_draw.cpp [] []
/src/tinygltf/examples/common/imgui/stb_rect_pack.h [] []
/src/tinygltf/examples/common/glm/test/core/core_func_integer.cpp [] []
/src/tinygltf/examples/common/OpenGLWindow/X11OpenGLWindow.h [] []
/src/tinygltf/examples/common/glm/test/core/core_func_exponential.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_color_space.cpp [] []
/src/tinygltf/examples/validator/app/tinygltf-validate.cc [] []
/src/tinygltf/examples/raytrace/render-config.cc [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_io.cpp [] []
/src/tinygltf/examples/common/lodepng.h [] []
/src/tinygltf/examples/common/imgui/imgui.cpp [] []
/src/tinygltf/examples/common/glm/glm/detail/_swizzle.hpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_swizzle.cpp [] []
/src/tinygltf/examples/common/picojson.h [] []
/src/tinygltf/examples/common/glm/test/core/core_type_mat3x3.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_quaternion.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_integer.cpp [] []
/src/tinygltf/examples/common/glm/glm/gtx/scalar_multiplication.hpp [] []
/src/tinygltf/examples/raytrace/nanosg.h [] []
/src/tinygltf/examples/common/imgui/stb_textedit.h [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_user_defined_types.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_integer_find_lsb.cpp [] []
/src/tinygltf/examples/common/lodepng.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_random.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_type_int.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_setup_message.cpp [] []
/src/tinygltf/examples/common/glm/glm/gtx/quaternion.hpp [] []
/src/tinygltf/tiny_gltf.h ['tests/fuzzer/fuzz_gltf.cc'] []
/src/tinygltf/examples/common/glm/test/external/gli/target.hpp [] []
/src/tinygltf/examples/common/glm/test/external/gli/texture.hpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_integer_find_msb.cpp [] []
/src/tinygltf/examples/gltfutil/texture_dumper.h [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_matrix_factorisation.cpp [] []
/src/tinygltf/loader_example.cc [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_matrix_inverse.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_round.cpp [] []
/src/tinygltf/examples/basic/shaders.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_type_mat4x4.cpp [] []
/src/tinygltf/examples/raytrace/nanort.h [] []
/src/tinygltf/examples/common/glm/glm/simd/common.h [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_common.cpp [] []
/src/tinygltf/examples/common/glm/glm/detail/type_gentype.hpp [] []
/src/tinygltf/examples/common/glm/glm/simd/geometric.h [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_matrix_interpolation.cpp [] []
/src/tinygltf/examples/common/nativefiledialog/src/nfd_gtk.c [] []
/src/tinygltf/examples/common/glm/test/external/gli/type.hpp [] []
/src/tinygltf/examples/common/glm/test/core/core_setup_force_size_t_length.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_dual_quaternion.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_vector_relational.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_type_vec1.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_range.cpp [] []
/src/tinygltf/examples/raytrace/gltf-loader.h [] []
/src/tinygltf/examples/validator/src/json-validator.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_type_ptr.cpp [] []
/src/tinygltf/examples/common/glm/test/external/gli/sampler.hpp [] []
/src/tinygltf/examples/common/glm/test/core/core_type_cast.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_setup_precision.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_func_integer_bit_count.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_type_aligned.cpp [] []
/src/tinygltf/examples/common/glm/glm/detail/type_vec.hpp [] []
/src/tinygltf/examples/common/imgui/stb_truetype.h [] []
/src/tinygltf/examples/common/glm/test/core/core_type_vec2.cpp [] []
/src/tinygltf/examples/basic/main.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_spline.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_simd_mat4.cpp [] []
/src/tinygltf/examples/common/glm/glm/detail/type_mat4x3.hpp [] []
/src/tinygltf/examples/common/imgui/ImGuizmo.cpp [] []
/src/tinygltf/examples/common/glm/glm/simd/integer.h [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_random.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_quaternion.cpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_type_aligned.cpp [] []
/src/tinygltf/examples/common/nativefiledialog/src/common.h [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_wrap.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_force_pure.cpp [] []
/src/tinygltf/examples/common/glm/test/external/gli/core/filter_compute.hpp [] []
/src/tinygltf/examples/common/glm/test/gtx/gtx_fast_trigonometry.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_integer.cpp [] []
/src/tinygltf/examples/common/glm/test/gtc/gtc_ulp.cpp [] []
/src/tinygltf/examples/common/glm/test/core/core_type_ctor.cpp [] []

Directories in report

Directory
/src/tinygltf/examples/common/ThirdPartyLibs/Glew/CustomGL/
/src/tinygltf/examples/common/nativefiledialog/src/
/src/tinygltf/examples/common/imgui/
/src/tinygltf/tests/
/src/tinygltf/examples/common/glm/glm/simd/
/src/tinygltf/examples/basic/
/src/tinygltf/
/src/tinygltf/examples/common/glm/test/core/
/src/tinygltf/examples/dxview/src/
/src/tinygltf/examples/validator/app/
/src/tinygltf/examples/gltfutil/
/src/tinygltf/examples/common/glm/test/gtc/
/src/tinygltf/examples/common/glm/test/gtx/
/src/tinygltf/examples/common/
/src/tinygltf/examples/common/OpenGLWindow/
/src/tinygltf/examples/common/glm/test/external/gli/core/
/src/tinygltf/examples/common/glm/glm/detail/
/src/tinygltf/examples/raytrace/
/src/tinygltf/examples/common/ThirdPartyLibs/Glew/
/src/tinygltf/examples/validator/src/
/src/tinygltf/tests/fuzzer/
/src/tinygltf/examples/common/glm/glm/gtx/
/src/tinygltf/examples/glview/
/src/tinygltf/examples/common/glm/test/external/gli/

Sink analyser for CWEs

This section contains multiple tables, each table contains a list of sink functions/methods found in the project for one of the CWE supported by the sink analyser, together with information like which fuzzers statically reach the sink functions/methods and possible call path to that sink functions/methods if it is not statically reached by any fuzzers. Column 1 is the function/method name of the sink functions/methods found in the project. Column 2 lists all fuzzers (or no fuzzers at all) that have covered that particular function method statically. Column 3 shows a list of possible call paths to reach the specific function/method call if none of the fuzzers cover the target function/method calls. Lastly, column 4 shows possible fuzzer blockers that prevent an existing fuzzer from reaching the target sink functions/methods dynamically.

Sink functions/methods found for CWE416

Target sink Reached by fuzzer Function call path Possible branch blockers
c_str [] Path 1
Path 2

N/A
get ['/src/tinygltf/tests/fuzzer/fuzz_gltf.cc'] N/A
Blocker function Arguments type Return type Constants touched
nlohmann::detail::lexer::scan_string
in /src/tinygltf/json.hpp:6874
[] token_type []
nlohmann::detail::lexer::scan_comment
in /src/tinygltf/json.hpp:7464
[] bool []
nlohmann::detail::lexer::scan_number
in /src/tinygltf/json.hpp:7589
[] token_type []
nlohmann::detail::parser::parser
in /src/tinygltf/json.hpp:10988
['InputAdapterType'] void []
operator""_json(constchar*s,std::size_tn)
in /src/tinygltf/examples/validator/src/json.hpp:12969
['char*', 'std::size_t'] nlohmann::json []
displayLoop
in /src/tinygltf/examples/basic/main.cpp:284
['Window', 'std::string'] void []
example::LoadGLTF
in /src/tinygltf/examples/raytrace/gltf-loader.cc:19
['std::string', 'float', 'std::vector >*', 'std::vector *', 'std::vector *'] bool []
main
in /src/tinygltf/examples/gltfutil/main.cc:133
['int', 'char*[]'] int []
JsonConstruct
in /src/tinygltf/tests/tester.cc:19
['char*'] tinygltf::detail::JsonDocument []
&operator>>(std::istream&is,picojson::value&x)
in /src/tinygltf/examples/common/picojson.h:1027
['std::istream', 'picojson::value'] std::istream []
example::LoadRenderConfig
in /src/tinygltf/examples/raytrace/render-config.cc:10
['example::RenderConfig*', 'char*'] bool []
parser::parse
in /src/tinygltf/examples/validator/src/json.hpp:11379
[] basic_json []
(3) boolsax_parse(constinput_format_tformat, json_sax_t*sax_, constboolstrict=true, constcbor_tag_handler_ttag_handler=cbor_tag_handler_t::error)
in /src/tinygltf/json.hpp:8484
['input_format_t', 'json_sax_t*'] JSON_HEDLEY_NON_NULL []
accept
in /src/tinygltf/json.hpp:24505
['detail::span_input_adapter'] bool []
nlohmann::detail::parser::accept
in /src/tinygltf/json.hpp:11070
[] bool []
from_ubjson
in /src/tinygltf/json.hpp:25536
['detail::span_input_adapter'] basic_json []
from_bson
in /src/tinygltf/json.hpp:25650
['detail::span_input_adapter'] basic_json []
operator[](UnpositionalTag)
in /src/tinygltf/tests/catch.hpp:4397
[] ArgBuilder []
Clara::CommandLine::parse
in /src/tinygltf/tests/catch.hpp:4485
['int', 'char*[]'] ConfigT []
Catch::TestCaseTracking::TrackerContext::startCycle
in /src/tinygltf/tests/catch.hpp:5516
[] void []
Catch::runTests
in /src/tinygltf/tests/catch.hpp:6231
['Ptr '] Totals []
Catch::DebugOutStream::DebugOutStream
in /src/tinygltf/tests/catch.hpp:6840
[] void []
TestCase::operator==(TestCaseconst&other)const
in /src/tinygltf/tests/catch.hpp:7463
['TestCase'] bool []
nlohmann::const_reference::at
in /src/tinygltf/examples/validator/src/json.hpp:1039
['size_type'] class basic_json { private: template friend struct detail::external_constructor; /// workaround type for MSVC using basic_json_t = basic_json ; public: using value_t = detail::value_t; // forward declarations template class iter_impl; template class json_reverse_iterator; class json_pointer; template using json_serializer = JSONSerializer ; ///////////////////// // container types // ///////////////////// /// @name container types /// The canonic container types to use @ref basic_json like any other STL /// container. /// @{ /// the type of elements in a basic_json container using value_type = basic_json; /// the type of an element reference using reference = value_type&; /// the type of an element const reference using const_reference = const value_type&; /// a type to represent differences between iterators using difference_type = std::ptrdiff_t; /// a type to represent container sizes using size_type = std::size_t; /// the allocator type using allocator_type = AllocatorType ; /// the type of an element pointer using pointer = typename std::allocator_traits ::pointer; /// the type of an element const pointer using const_pointer = typename std::allocator_traits ::const_pointer; /// an iterator for a basic_json container using iterator = iter_impl ; /// a const iterator for a basic_json container using const_iterator = iter_impl ; /// a reverse iterator for a basic_json container using reverse_iterator = json_reverse_iterator ; /// a const reverse iterator for a basic_json container using const_reverse_iterator = json_reverse_iterator ; /// @} /*! @brief returns the allocator associated with the container */ static allocator_type get_allocator() { return allocator_type(); } /*! @brief returns version information on the library This function returns a JSON object with information about the library, including the version number and information on the platform and compiler. @return JSON object holding version information key | description ----------- | --------------- `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). `copyright` | The copyright line for the library as string. `name` | The name of the library as string. `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. `url` | The URL of the project as string. `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). @liveexample{The following code shows an example output of the `meta()` function.,meta} @complexity Constant. @since 2.1.0 */ static basic_json meta() { basic_json result; result["copyright"] = "(C) 2013-2017 Niels Lohmann"; result["name"] = "JSON for Modern C++"; result["url"] = "https://github.com/nlohmann/json"; result["version"] = { {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, {"patch", 1} }; #ifdef _WIN32 result["platform"] = "win32"; #elif defined __linux__ result["platform"] = "linux"; #elif defined __APPLE__ result["platform"] = "apple"; #elif defined __unix__ result["platform"] = "unix"; #else result["platform"] = "unknown"; #endif #if defined(__clang__) result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; #elif defined(__ICC) || defined(__INTEL_COMPILER) result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; #elif defined(__GNUC__) || defined(__GNUG__) result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; #elif defined(__HP_cc) || defined(__HP_aCC) result["compiler"] = "hp" #elif defined(__IBMCPP__) result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; #elif defined(_MSC_VER) result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; #elif defined(__PGI) result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; #elif defined(__SUNPRO_CC) result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; #else result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; #endif #ifdef __cplusplus result["compiler"]["c++"] = std::to_string(__cplusplus); #else result["compiler"]["c++"] = "unknown"; #endif return result; } /////////////////////////// // JSON value data types // /////////////////////////// /// @name JSON value data types /// The data types to store a JSON value. These types are derived from /// the template arguments passed to class @ref basic_json. /// @{ /*! @brief a type for an object [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: > An object is an unordered collection of zero or more name/value pairs, > where a name is a string and a value is a string, number, boolean, null, > object, or array. To store objects in C++, a type is defined by the template parameters described below. @tparam ObjectType the container to store objects (e.g., `std::map` or `std::unordered_map`) @tparam StringType the type of the keys or names (e.g., `std::string`). The comparison function `std::less ` is used to order elements inside the container. @tparam AllocatorType the allocator to use for objects (e.g., `std::allocator`) #### Default type With the default values for @a ObjectType (`std::map`), @a StringType (`std::string`), and @a AllocatorType (`std::allocator`), the default value for @a object_t is: @code {.cpp} std::map< std::string, // key_type basic_json, // value_type std::less , // key_compare std::allocator > // allocator_type > @endcode #### Behavior The choice of @a object_t influences the behavior of the JSON class. With the default type, objects have the following behavior: - When all names are unique, objects will be interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings. - When the names within an object are not unique, later stored name/value pairs overwrite previously stored name/value pairs, leaving the used names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will be treated as equal and both stored as `{"key": 1}`. - Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see @ref dump) in this order. For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and serialized as `{"a": 2, "b": 1}`. - When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense that they will not be affected by these differences. For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be treated as equal. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the maximum depth of nesting. In this class, the object's limit of nesting is not constraint explicitly. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the @ref max_size function of a JSON object. #### Storage Objects are stored as pointers in a @ref basic_json type. That is, for any access to object values, a pointer of type `object_t*` must be dereferenced. @sa @ref array_t -- type for an array value @since version 1.0.0 @note The order name/value pairs are added to the object is *not* preserved by the library. Therefore, iterating an object may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to [RFC 7159](http://rfc7159.net/rfc7159), because any order implements the specified "unordered" nature of JSON objects. */ using object_t = ObjectType , AllocatorType >>; /*! @brief a type for an array [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: > An array is an ordered sequence of zero or more values. To store objects in C++, a type is defined by the template parameters explained below. @tparam ArrayType container type to store arrays (e.g., `std::vector` or `std::list`) @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) #### Default type With the default values for @a ArrayType (`std::vector`) and @a AllocatorType (`std::allocator`), the default value for @a array_t is: @code {.cpp} std::vector< basic_json, // value_type std::allocator // allocator_type > @endcode #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the maximum depth of nesting. In this class, the array's limit of nesting is not constraint explicitly. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the @ref max_size function of a JSON array. #### Storage Arrays are stored as pointers in a @ref basic_json type. That is, for any access to array values, a pointer of type `array_t*` must be dereferenced. @sa @ref object_t -- type for an object value @since version 1.0.0 */ using array_t = ArrayType >; /*! @brief a type for a string [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: > A string is a sequence of zero or more Unicode characters. To store objects in C++, a type is defined by the template parameter described below. Unicode values are split by the JSON class into byte-sized characters during deserialization. @tparam StringType the container to store strings (e.g., `std::string`). Note this container is used for keys/names in objects, see @ref object_t. #### Default type With the default values for @a StringType (`std::string`), the default value for @a string_t is: @code {.cpp} std::string @endcode #### Encoding Strings are stored in UTF-8 encoding. Therefore, functions like `std::string::size()` or `std::string::length()` return the number of bytes in the string rather than the number of characters or glyphs. #### String comparison [RFC 7159](http://rfc7159.net/rfc7159) states: > Software implementations are typically required to test names of object > members for equality. Implementations that transform the textual > representation into sequences of Unicode code units and then perform the > comparison numerically, code unit by code unit, are interoperable in the > sense that implementations will agree in all cases on equality or > inequality of two strings. For example, implementations that compare > strings with escaped characters unconverted may incorrectly find that > `"a\\b"` and `"a\u005Cb"` are not equal. This implementation is interoperable as it does compare strings code unit by code unit. #### Storage String values are stored as pointers in a @ref basic_json type. That is, for any access to string values, a pointer of type `string_t*` must be dereferenced. @since version 1.0.0 */ using string_t = StringType; /*! @brief a type for a boolean [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a type which differentiates the two literals `true` and `false`. To store objects in C++, a type is defined by the template parameter @a BooleanType which chooses the type to use. #### Default type With the default values for @a BooleanType (`bool`), the default value for @a boolean_t is: @code {.cpp} bool @endcode #### Storage Boolean values are stored directly inside a @ref basic_json type. @since version 1.0.0 */ using boolean_t = BooleanType; /*! @brief a type for a number (integer) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store integer numbers in C++, a type is defined by the template parameter @a NumberIntegerType which chooses the type to use. #### Default type With the default values for @a NumberIntegerType (`int64_t`), the default value for @a number_integer_t is: @code {.cpp} int64_t @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For instance, the C++ integer literal `010` will be serialized to `8`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the range and precision of numbers. When the default type is used, the maximal integer number that can be stored is `9223372036854775807` (INT64_MAX) and the minimal integer number that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as @ref number_unsigned_t or @ref number_float_t. [RFC 7159](http://rfc7159.net/rfc7159) further states: > Note that when such software is used, numbers that are integers and are > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense > that implementations will agree exactly on their numeric values. As this range is a subrange of the exactly supported range [INT64_MIN, INT64_MAX], this class's integer type is interoperable. #### Storage Integer number values are stored directly inside a @ref basic_json type. @sa @ref number_float_t -- type for number values (floating-point) @sa @ref number_unsigned_t -- type for number values (unsigned integer) @since version 1.0.0 */ using number_integer_t = NumberIntegerType; /*! @brief a type for a number (unsigned) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store unsigned integer numbers in C++, a type is defined by the template parameter @a NumberUnsignedType which chooses the type to use. #### Default type With the default values for @a NumberUnsignedType (`uint64_t`), the default value for @a number_unsigned_t is: @code {.cpp} uint64_t @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For instance, the C++ integer literal `010` will be serialized to `8`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the range and precision of numbers. When the default type is used, the maximal integer number that can be stored is `18446744073709551615` (UINT64_MAX) and the minimal integer number that can be stored is `0`. Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as @ref number_integer_t or @ref number_float_t. [RFC 7159](http://rfc7159.net/rfc7159) further states: > Note that when such software is used, numbers that are integers and are > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the number_integer_t type) of the exactly supported range [0, UINT64_MAX], this class's integer type is interoperable. #### Storage Integer number values are stored directly inside a @ref basic_json type. @sa @ref number_float_t -- type for number values (floating-point) @sa @ref number_integer_t -- type for number values (integer) @since version 2.0.0 */ using number_unsigned_t = NumberUnsignedType; /*! @brief a type for a number (floating-point) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store floating-point numbers in C++, a type is defined by the template parameter @a NumberFloatType which chooses the type to use. #### Default type With the default values for @a NumberFloatType (`double`), the default value for @a number_float_t is: @code {.cpp} double @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in floating-point literals will be ignored. Internally, the value will be stored as decimal number. For instance, the C++ floating-point literal `01.2` will be serialized to `1.2`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) states: > This specification allows implementations to set limits on the range and > precision of numbers accepted. Since software that implements IEEE > 754-2008 binary64 (double precision) numbers is generally available and > widely used, good interoperability can be achieved by implementations > that expect no more precision or range than these provide, in the sense > that implementations will approximate JSON numbers within the expected > precision. This implementation does exactly follow this approach, as it uses double precision floating-point numbers. Note values smaller than `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` will be stored as NaN internally and be serialized to `null`. #### Storage Floating-point number values are stored directly inside a @ref basic_json type. @sa @ref number_integer_t -- type for number values (integer) @sa @ref number_unsigned_t -- type for number values (unsigned integer) @since version 1.0.0 */ using number_float_t = NumberFloatType; /// @} private: /// helper for exception-safe object creation template static T* create(Args&& ... args) { AllocatorType alloc; auto deleter = [&](T * object) { alloc.deallocate(object, 1); }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward (args)...); assert(object != nullptr); return object.release(); } //////////////////////// // JSON value storage // //////////////////////// /*! @brief a JSON value The actual storage for a JSON value of the @ref basic_json class. This union combines the different storage types for the JSON value types defined in @ref value_t. JSON type | value_t type | used type --------- | --------------- | ------------------------ object | object | pointer to @ref object_t array | array | pointer to @ref array_t string | string | pointer to @ref string_t boolean | boolean | @ref boolean_t number | number_integer | @ref number_integer_t number | number_unsigned | @ref number_unsigned_t number | number_float | @ref number_float_t null | null | *no value is stored* @note Variable-length types (objects, arrays, and strings) are stored as pointers. The size of the union should not exceed 64 bits if the default value types are used. @since version 1.0.0 */ union json_value { /// object (stored with pointer to save storage) object_t* object; /// array (stored with pointer to save storage) array_t* array; /// string (stored with pointer to save storage) string_t* string; /// boolean boolean_t boolean; /// number (integer) number_integer_t number_integer; /// number (unsigned integer) number_unsigned_t number_unsigned; /// number (floating-point) number_float_t number_float; /// default constructor (for null values) json_value() = default; /// constructor for booleans json_value(boolean_t v) noexcept : boolean(v) {} /// constructor for numbers (integer) json_value(number_integer_t v) noexcept : number_integer(v) {} /// constructor for numbers (unsigned) json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} /// constructor for numbers (floating-point) json_value(number_float_t v) noexcept : number_float(v) {} /// constructor for empty values of a given type json_value(value_t t) { switch (t) { case value_t::object: { object = create (); break; } case value_t::array: { array = create (); break; } case value_t::string: { string = create (""); break; } case value_t::boolean: { boolean = boolean_t(false); break; } case value_t::number_integer: { number_integer = number_integer_t(0); break; } case value_t::number_unsigned: { number_unsigned = number_unsigned_t(0); break; } case value_t::number_float: { number_float = number_float_t(0.0); break; } case value_t::null: { break; } default: { if (t == value_t::null) { JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE } break; } } } /// constructor for strings json_value(const string_t& value) { string = create (value); } /// constructor for objects json_value(const object_t& value) { object = create (value); } /// constructor for arrays json_value(const array_t& value) { array = create (value); } }; /*! @brief checks the class invariants This function asserts the class invariants. It needs to be called at the end of every constructor to make sure that created objects respect the invariant. Furthermore, it has to be called each time the type of a JSON value is changed, because the invariant expresses a relationship between @a m_type and @a m_value. */ void assert_invariant() const { assert(m_type != value_t::object or m_value.object != nullptr); assert(m_type != value_t::array or m_value.array != nullptr); assert(m_type != value_t::string or m_value.string != nullptr); } public: ////////////////////////// // JSON parser callback // ////////////////////////// /*! @brief JSON callback events This enumeration lists the parser events that can trigger calling a callback function of type @ref parser_callback_t during parsing. @image html callback_events.png "Example when certain parse events are triggered" @since version 1.0.0 */ enum class parse_event_t : uint8_t { /// the parser read `{` and started to process a JSON object object_start, /// the parser read `}` and finished processing a JSON object object_end, /// the parser read `[` and started to process a JSON array array_start, /// the parser read `]` and finished processing a JSON array array_end, /// the parser read a key of a value in an object key, /// the parser finished reading a JSON value value }; /*! @brief per-element parser callback type With a parser callback function, the result of parsing a JSON text can be influenced. When passed to @ref parse(std::istream&, const parser_callback_t) or @ref parse(const CharT, const parser_callback_t), it is called on certain events (passed as @ref parse_event_t via parameter @a event) with a set recursion depth @a depth and context JSON value @a parsed. The return value of the callback function is a boolean indicating whether the element that emitted the callback shall be kept or not. We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values of the parameters @a depth, @a event, and @a parsed. parameter @a event | description | parameter @a depth | parameter @a parsed ------------------ | ----------- | ------------------ | ------------------- parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value @image html callback_events.png "Example when certain parse events are triggered" Discarding a value (i.e., returning `false`) has different effects depending on the context in which function was called: - Discarded values in structured types are skipped. That is, the parser will behave as if the discarded value was never read. - In case a value outside a structured type is skipped, it is replaced with `null`. This case happens if the top-level element is skipped. @param[in] depth the depth of the recursion during parsing @param[in] event an event of type parse_event_t indicating the context in the callback function has been called @param[in,out] parsed the current intermediate parse result; note that writing to this value has no effect for parse_event_t::key events @return Whether the JSON value which called the function during parsing should be kept (`true`) or not (`false`). In the latter case, it is either skipped completely or replaced by an empty discarded object. @sa @ref parse(std::istream&, parser_callback_t) or @ref parse(const CharT, const parser_callback_t) for examples @since version 1.0.0 */ using parser_callback_t = std::function ; ////////////////// // constructors // ////////////////// /// @name constructors and destructors /// Constructors of class @ref basic_json, copy/move constructor, copy /// assignment, static functions creating objects, and the destructor. /// @{ /*! @brief create an empty value with a given type Create an empty JSON value with a given type. The value will be default initialized with an empty value which depends on the type: Value type | initial value ----------- | ------------- null | `null` boolean | `false` string | `""` number | `0` object | `{}` array | `[]` @param[in] value_type the type of the value to create @complexity Constant. @throw std::bad_alloc if allocation for object, array, or string value fails @liveexample{The following code shows the constructor for different @ref value_t values,basic_json__value_t} @since version 1.0.0 */ basic_json(const value_t value_type) : m_type(value_type), m_value(value_type) { assert_invariant(); } /*! @brief create a null object Create a `null` JSON value. It either takes a null pointer as parameter (explicitly creating `null`) or no parameter (implicitly creating `null`). The passed null pointer itself is not read -- it is only used to choose the right constructor. @complexity Constant. @exceptionsafety No-throw guarantee: this constructor never throws exceptions. @liveexample{The following code shows the constructor with and without a null pointer parameter.,basic_json__nullptr_t} @since version 1.0.0 */ basic_json(std::nullptr_t = nullptr) noexcept : basic_json(value_t::null) { assert_invariant(); } /*! @brief create a JSON value This is a "catch all" constructor for all compatible JSON types; that is, types for which a `to_json()` method exsits. The constructor forwards the parameter @a val to that method (to `json_serializer ::to_json` method with `U = uncvref_t `, to be exact). Template type @a CompatibleType includes, but is not limited to, the following types: - **arrays**: @ref array_t and all kinds of compatible containers such as `std::vector`, `std::deque`, `std::list`, `std::forward_list`, `std::array`, `std::set`, `std::unordered_set`, `std::multiset`, and `unordered_multiset` with a `value_type` from which a @ref basic_json value can be constructed. - **objects**: @ref object_t and all kinds of compatible associative containers such as `std::map`, `std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with a `key_type` compatible to @ref string_t and a `value_type` from which a @ref basic_json value can be constructed. - **strings**: @ref string_t, string literals, and all compatible string containers can be used. - **numbers**: @ref number_integer_t, @ref number_unsigned_t, @ref number_float_t, and all convertible number types such as `int`, `size_t`, `int64_t`, `float` or `double` can be used. - **boolean**: @ref boolean_t / `bool` can be used. See the examples below. @tparam CompatibleType a type such that: - @a CompatibleType is not derived from `std::istream`, - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move constructors), - @a CompatibleType is not a @ref basic_json nested type (e.g., @ref json_pointer, @ref iterator, etc ...) - @ref @ref json_serializer has a `to_json(basic_json_t&, CompatibleType&&)` method @tparam U = `uncvref_t ` @param[in] val the value to be forwarded @complexity Usually linear in the size of the passed @a val, also depending on the implementation of the called `to_json()` method. @throw what `json_serializer ::to_json()` throws @liveexample{The following code shows the constructor with several compatible types.,basic_json__CompatibleType} @since version 2.1.0 */ template , detail::enable_if_t ::value and not std::is_same ::value and not detail::is_basic_json_nested_type< basic_json_t, U>::value and detail::has_to_json ::value, int> = 0> basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer ::to_json( std::declval (), std::forward (val)))) { JSONSerializer ::to_json(*this, std::forward (val)); assert_invariant(); } /*! @brief create a container (array or object) from an initializer list Creates a JSON value of type array or object from the passed initializer list @a init. In case @a type_deduction is `true` (default), the type of the JSON value to be created is deducted from the initializer list @a init according to the following rules: 1. If the list is empty, an empty JSON object value `{}` is created. 2. If the list consists of pairs whose first element is a string, a JSON object value is created where the first elements of the pairs are treated as keys and the second elements are as values. 3. In all other cases, an array is created. The rules aim to create the best fit between a C++ initializer list and JSON values. The rationale is as follows: 1. The empty initializer list is written as `{}` which is exactly an empty JSON object. 2. C++ has now way of describing mapped types other than to list a list of pairs. As JSON requires that keys must be of type string, rule 2 is the weakest constraint one can pose on initializer lists to interpret them as an object. 3. In all other cases, the initializer list could not be interpreted as JSON object type, so interpreting it as JSON array type is safe. With the rules described above, the following JSON values cannot be expressed by an initializer list: - the empty array (`[]`): use @ref array(std::initializer_list ) with an empty initializer list in this case - arrays whose elements satisfy rule 2: use @ref array(std::initializer_list ) with the same initializer list in this case @note When used without parentheses around an empty initializer list, @ref basic_json() is called instead of this function, yielding the JSON null value. @param[in] init initializer list with JSON values @param[in] type_deduction internal parameter; when set to `true`, the type of the JSON value is deducted from the initializer list @a init; when set to `false`, the type provided via @a manual_type is forced. This mode is used by the functions @ref array(std::initializer_list ) and @ref object(std::initializer_list ). @param[in] manual_type internal parameter; when @a type_deduction is set to `false`, the created JSON value will use the provided type (only @ref value_t::array and @ref value_t::object are valid); when @a type_deduction is set to `true`, this parameter has no effect @throw std::domain_error if @a type_deduction is `false`, @a manual_type is `value_t::object`, but @a init contains an element which is not a pair whose first element is a string; example: `"cannot create object from initializer list"` @complexity Linear in the size of the initializer list @a init. @liveexample{The example below shows how JSON values are created from initializer lists.,basic_json__list_init_t} @sa @ref array(std::initializer_list ) -- create a JSON array value from an initializer list @sa @ref object(std::initializer_list ) -- create a JSON object value from an initializer list @since version 1.0.0 */ basic_json(std::initializer_list init, bool type_deduction = true, value_t manual_type = value_t::array) { // check if each element is an array with two elements whose first // element is a string bool is_an_object = std::all_of(init.begin(), init.end(), [](const basic_json & element) { return element.is_array() and element.size() == 2 and element[0].is_string(); }); // adjust type if type deduction is not wanted if (not type_deduction) { // if array is wanted, do not create an object though possible if (manual_type == value_t::array) { is_an_object = false; } // if object is wanted but impossible, throw an exception if (manual_type == value_t::object and not is_an_object) { JSON_THROW(std::domain_error("cannot create object from initializer list")); } } if (is_an_object) { // the initializer list is a list of pairs -> create object m_type = value_t::object; m_value = value_t::object; std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); }); } else { // the initializer list describes an array -> create array m_type = value_t::array; m_value.array = create (init); } assert_invariant(); } /*! @brief explicitly create an array from an initializer list Creates a JSON array value from a given initializer list. That is, given a list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the initializer list is empty, the empty array `[]` is created. @note This function is only needed to express two edge cases that cannot be realized with the initializer list constructor (@ref basic_json(std::initializer_list , bool, value_t)). These cases are: 1. creating an array whose elements are all pairs whose first element is a string -- in this case, the initializer list constructor would create an object, taking the first elements as keys 2. creating an empty array -- passing the empty initializer list to the initializer list constructor yields an empty object @param[in] init initializer list with JSON values to create an array from (optional) @return JSON array value @complexity Linear in the size of @a init. @liveexample{The following code shows an example for the `array` function.,array} @sa @ref basic_json(std::initializer_list , bool, value_t) -- create a JSON value from an initializer list @sa @ref object(std::initializer_list ) -- create a JSON object value from an initializer list @since version 1.0.0 */ static basic_json array(std::initializer_list init = std::initializer_list ()) { return basic_json(init, false, value_t::array); } /*! @brief explicitly create an object from an initializer list Creates a JSON object value from a given initializer list. The initializer lists elements must be pairs, and their first elements must be strings. If the initializer list is empty, the empty object `{}` is created. @note This function is only added for symmetry reasons. In contrast to the related function @ref array(std::initializer_list ), there are no cases which can only be expressed by this function. That is, any initializer list @a init can also be passed to the initializer list constructor @ref basic_json(std::initializer_list , bool, value_t). @param[in] init initializer list to create an object from (optional) @return JSON object value @throw std::domain_error if @a init is not a pair whose first elements are strings; thrown by @ref basic_json(std::initializer_list , bool, value_t) @complexity Linear in the size of @a init. @liveexample{The following code shows an example for the `object` function.,object} @sa @ref basic_json(std::initializer_list , bool, value_t) -- create a JSON value from an initializer list @sa @ref array(std::initializer_list ) -- create a JSON array value from an initializer list @since version 1.0.0 */ static basic_json object(std::initializer_list init = std::initializer_list ()) { return basic_json(init, false, value_t::object); } /*! @brief construct an array with count copies of given value Constructs a JSON array value by creating @a cnt copies of a passed value. In case @a cnt is `0`, an empty array is created. As postcondition, `std::distance(begin(),end()) == cnt` holds. @param[in] cnt the number of JSON copies of @a val to create @param[in] val the JSON value to copy @complexity Linear in @a cnt. @liveexample{The following code shows examples for the @ref basic_json(size_type\, const basic_json&) constructor.,basic_json__size_type_basic_json} @since version 1.0.0 */ basic_json(size_type cnt, const basic_json& val) : m_type(value_t::array) { m_value.array = create (cnt, val); assert_invariant(); } /*! @brief construct a JSON container given an iterator range Constructs the JSON value with the contents of the range `[first, last)`. The semantics depends on the different types a JSON value can have: - In case of primitive types (number, boolean, or string), @a first must be `begin()` and @a last must be `end()`. In this case, the value is copied. Otherwise, std::out_of_range is thrown. - In case of structured types (array, object), the constructor behaves as similar versions for `std::vector`. - In case of a null type, std::domain_error is thrown. @tparam InputIT an input iterator type (@ref iterator or @ref const_iterator) @param[in] first begin of the range to copy from (included) @param[in] last end of the range to copy from (excluded) @pre Iterators @a first and @a last must be initialized. **This precondition is enforced with an assertion.** @throw std::domain_error if iterators are not compatible; that is, do not belong to the same JSON value; example: `"iterators are not compatible"` @throw std::out_of_range if iterators are for a primitive type (number, boolean, or string) where an out of range error can be detected easily; example: `"iterators out of range"` @throw std::bad_alloc if allocation for object, array, or string fails @throw std::domain_error if called with a null value; example: `"cannot use construct with iterators from null"` @complexity Linear in distance between @a first and @a last. @liveexample{The example below shows several ways to create JSON values by specifying a subrange with iterators.,basic_json__InputIt_InputIt} @since version 1.0.0 */ template ::value or std::is_same ::value, int>::type = 0> basic_json(InputIT first, InputIT last) { assert(first.m_object != nullptr); assert(last.m_object != nullptr); // make sure iterator fits the current value if (first.m_object != last.m_object) { JSON_THROW(std::domain_error("iterators are not compatible")); } // copy type from first iterator m_type = first.m_object->m_type; // check if iterator range is complete for primitive values switch (m_type) { case value_t::boolean: case value_t::number_float: case value_t::number_integer: case value_t::number_unsigned: case value_t::string: { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { JSON_THROW(std::out_of_range("iterators out of range")); } break; } default: { break; } } switch (m_type) { case value_t::number_integer: { m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { m_value = *first.m_object->m_value.string; break; } case value_t::object: { m_value.object = create (first.m_it.object_iterator, last.m_it.object_iterator); break; } case value_t::array: { m_value.array = create (first.m_it.array_iterator, last.m_it.array_iterator); break; } default: { JSON_THROW(std::domain_error("cannot use construct with iterators from " + first.m_object->type_name())); } } assert_invariant(); } /*! @brief construct a JSON value given an input stream @param[in,out] i stream to read a serialized JSON value from @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @note A UTF-8 byte order mark is silently ignored. @deprecated This constructor is deprecated and will be removed in version 3.0.0 to unify the interface of the library. Deserialization will be done by stream operators or by calling one of the `parse` functions, e.g. @ref parse(std::istream&, const parser_callback_t). That is, calls like `json j(i);` for an input stream @a i need to be replaced by `json j = json::parse(i);`. See the example below. @liveexample{The example below demonstrates constructing a JSON value from a `std::stringstream` with and without callback function.,basic_json__istream} @since version 2.0.0, deprecated in version 2.0.3, to be removed in version 3.0.0 */ JSON_DEPRECATED explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) { *this = parser(i, cb).parse(); assert_invariant(); } /////////////////////////////////////// // other constructors and destructor // /////////////////////////////////////// /*! @brief copy constructor Creates a copy of a given JSON value. @param[in] other the JSON value to copy @complexity Linear in the size of @a other. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. - As postcondition, it holds: `other == basic_json(other)`. @throw std::bad_alloc if allocation for object, array, or string fails. @liveexample{The following code shows an example for the copy constructor.,basic_json__basic_json} @since version 1.0.0 */ basic_json(const basic_json& other) : m_type(other.m_type) { // check of passed value is valid other.assert_invariant(); switch (m_type) { case value_t::object: { m_value = *other.m_value.object; break; } case value_t::array: { m_value = *other.m_value.array; break; } case value_t::string: { m_value = *other.m_value.string; break; } case value_t::boolean: { m_value = other.m_value.boolean; break; } case value_t::number_integer: { m_value = other.m_value.number_integer; break; } case value_t::number_unsigned: { m_value = other.m_value.number_unsigned; break; } case value_t::number_float: { m_value = other.m_value.number_float; break; } default: { break; } } assert_invariant(); } /*! @brief move constructor Move constructor. Constructs a JSON value with the contents of the given value @a other using move semantics. It "steals" the resources from @a other and leaves it as JSON null value. @param[in,out] other value to move to this object @post @a other is a JSON null value @complexity Constant. @liveexample{The code below shows the move constructor explicitly called via std::move.,basic_json__moveconstructor} @since version 1.0.0 */ basic_json(basic_json&& other) noexcept : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) { // check that passed value is valid other.assert_invariant(); // invalidate payload other.m_type = value_t::null; other.m_value = {}; assert_invariant(); } /*! @brief copy assignment Copy assignment operator. Copies a JSON value via the "copy and swap" strategy: It is expressed in terms of the copy constructor, destructor, and the swap() member function. @param[in] other value to copy from @complexity Linear. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. @liveexample{The code below shows and example for the copy assignment. It creates a copy of value `a` which is then swapped with `b`. Finally\, the copy of `a` (which is the null value after the swap) is destroyed.,basic_json__copyassignment} @since version 1.0.0 */ reference& operator=(basic_json other) noexcept ( std::is_nothrow_move_constructible ::value and std::is_nothrow_move_assignable ::value and std::is_nothrow_move_constructible ::value and std::is_nothrow_move_assignable ::value ) { // check that passed value is valid other.assert_invariant(); using std::swap; swap(m_type, other.m_type); swap(m_value, other.m_value); assert_invariant(); return *this; } /*! @brief destructor Destroys the JSON value and frees all allocated memory. @complexity Linear. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. - All stored elements are destroyed and all memory is freed. @since version 1.0.0 */ ~basic_json() { assert_invariant(); switch (m_type) { case value_t::object: { AllocatorType alloc; alloc.destroy(m_value.object); alloc.deallocate(m_value.object, 1); break; } case value_t::array: { AllocatorType alloc; alloc.destroy(m_value.array); alloc.deallocate(m_value.array, 1); break; } case value_t::string: { AllocatorType alloc; alloc.destroy(m_value.string); alloc.deallocate(m_value.string, 1); break; } default: { // all other types need no specific destructor break; } } } /// @} public: /////////////////////// // object inspection // /////////////////////// /// @name object inspection /// Functions to inspect the type of a JSON value. /// @{ /*! @brief serialization Serialization function for JSON values. The function tries to mimic Python's `json.dumps()` function, and currently supports its @a indent parameter. @param[in] indent If indent is nonnegative, then array elements and object members will be pretty-printed with that indent level. An indent level of `0` will only insert newlines. `-1` (the default) selects the most compact representation. @return string containing the serialization of the JSON value @complexity Linear. @liveexample{The following example shows the effect of different @a indent parameters to the result of the serialization.,dump} @see https://docs.python.org/2/library/json.html#json.dump @since version 1.0.0 */ string_t dump(const int indent = -1) const { std::stringstream ss; if (indent >= 0) { dump(ss, true, static_cast (indent)); } else { dump(ss, false, 0); } return ss.str(); } /*! @brief return the type of the JSON value (explicit) Return the type of the JSON value as a value from the @ref value_t enumeration. @return the type of the JSON value @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `type()` for all JSON types.,type} @since version 1.0.0 */ constexpr value_t type() const noexcept { return m_type; } /*! @brief return whether type is primitive This function returns true iff the JSON type is primitive (string, number, boolean, or null). @return `true` if type is primitive (string, number, boolean, or null), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_primitive()` for all JSON types.,is_primitive} @sa @ref is_structured() -- returns whether JSON value is structured @sa @ref is_null() -- returns whether JSON value is `null` @sa @ref is_string() -- returns whether JSON value is a string @sa @ref is_boolean() -- returns whether JSON value is a boolean @sa @ref is_number() -- returns whether JSON value is a number @since version 1.0.0 */ constexpr bool is_primitive() const noexcept { return is_null() or is_string() or is_boolean() or is_number(); } /*! @brief return whether type is structured This function returns true iff the JSON type is structured (array or object). @return `true` if type is structured (array or object), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_structured()` for all JSON types.,is_structured} @sa @ref is_primitive() -- returns whether value is primitive @sa @ref is_array() -- returns whether value is an array @sa @ref is_object() -- returns whether value is an object @since version 1.0.0 */ constexpr bool is_structured() const noexcept { return is_array() or is_object(); } /*! @brief return whether value is null This function returns true iff the JSON value is null. @return `true` if type is null, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_null()` for all JSON types.,is_null} @since version 1.0.0 */ constexpr bool is_null() const noexcept { return m_type == value_t::null; } /*! @brief return whether value is a boolean This function returns true iff the JSON value is a boolean. @return `true` if type is boolean, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_boolean()` for all JSON types.,is_boolean} @since version 1.0.0 */ constexpr bool is_boolean() const noexcept { return m_type == value_t::boolean; } /*! @brief return whether value is a number This function returns true iff the JSON value is a number. This includes both integer and floating-point values. @return `true` if type is number (regardless whether integer, unsigned integer or floating-type), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number()` for all JSON types.,is_number} @sa @ref is_number_integer() -- check if value is an integer or unsigned integer number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 1.0.0 */ constexpr bool is_number() const noexcept { return is_number_integer() or is_number_float(); } /*! @brief return whether value is an integer number This function returns true iff the JSON value is an integer or unsigned integer number. This excludes floating-point values. @return `true` if type is an integer or unsigned integer number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_integer()` for all JSON types.,is_number_integer} @sa @ref is_number() -- check if value is a number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 1.0.0 */ constexpr bool is_number_integer() const noexcept { return m_type == value_t::number_integer or m_type == value_t::number_unsigned; } /*! @brief return whether value is an unsigned integer number This function returns true iff the JSON value is an unsigned integer number. This excludes floating-point and (signed) integer values. @return `true` if type is an unsigned integer number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_unsigned()` for all JSON types.,is_number_unsigned} @sa @ref is_number() -- check if value is a number @sa @ref is_number_integer() -- check if value is an integer or unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 2.0.0 */ constexpr bool is_number_unsigned() const noexcept { return m_type == value_t::number_unsigned; } /*! @brief return whether value is a floating-point number This function returns true iff the JSON value is a floating-point number. This excludes integer and unsigned integer values. @return `true` if type is a floating-point number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_float()` for all JSON types.,is_number_float} @sa @ref is_number() -- check if value is number @sa @ref is_number_integer() -- check if value is an integer number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @since version 1.0.0 */ constexpr bool is_number_float() const noexcept { return m_type == value_t::number_float; } /*! @brief return whether value is an object This function returns true iff the JSON value is an object. @return `true` if type is object, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_object()` for all JSON types.,is_object} @since version 1.0.0 */ constexpr bool is_object() const noexcept { return m_type == value_t::object; } /*! @brief return whether value is an array This function returns true iff the JSON value is an array. @return `true` if type is array, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_array()` for all JSON types.,is_array} @since version 1.0.0 */ constexpr bool is_array() const noexcept { return m_type == value_t::array; } /*! @brief return whether value is a string This function returns true iff the JSON value is a string. @return `true` if type is string, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_string()` for all JSON types.,is_string} @since version 1.0.0 */ constexpr bool is_string() const noexcept { return m_type == value_t::string; } /*! @brief return whether value is discarded This function returns true iff the JSON value was discarded during parsing with a callback function (see @ref parser_callback_t). @note This function will always be `false` for JSON values after parsing. That is, discarded values can only occur during parsing, but will be removed when inside a structured value or replaced by null in other cases. @return `true` if type is discarded, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_discarded()` for all JSON types.,is_discarded} @since version 1.0.0 */ constexpr bool is_discarded() const noexcept { return m_type == value_t::discarded; } /*! @brief return the type of the JSON value (implicit) Implicitly return the type of the JSON value as a value from the @ref value_t enumeration. @return the type of the JSON value @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies the @ref value_t operator for all JSON types.,operator__value_t} @since version 1.0.0 */ constexpr operator value_t() const noexcept { return m_type; } /// @} private: ////////////////// // value access // ////////////////// /// get a boolean (explicit) boolean_t get_impl(boolean_t* /*unused*/) const { if (is_boolean()) { return m_value.boolean; } JSON_THROW(std::domain_error("type must be boolean, but is " + type_name())); } /// get a pointer to the value (object) object_t* get_impl_ptr(object_t* /*unused*/) noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (array) array_t* get_impl_ptr(array_t* /*unused*/) noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (string) string_t* get_impl_ptr(string_t* /*unused*/) noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (boolean) boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /*! @brief helper function to implement get_ref() This funcion helps to implement get_ref() without code duplication for const and non-const overloads @tparam ThisType will be deduced as `basic_json` or `const basic_json` @throw std::domain_error if ReferenceType does not match underlying value type of the current JSON */ template static ReferenceType get_ref_impl(ThisType& obj) { // helper type using PointerType = typename std::add_pointer ::type; // delegate the call to get_ptr<>() auto ptr = obj.template get_ptr (); if (ptr != nullptr) { return *ptr; } JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " + obj.type_name())); } public: /// @name value access /// Direct access to the stored value of a JSON value. /// @{ /*! @brief get special-case overload This overloads avoids a lot of template boilerplate, it can be seen as the identity method @tparam BasicJsonType == @ref basic_json @return a copy of *this @complexity Constant. @since version 2.1.0 */ template < typename BasicJsonType, detail::enable_if_t ::type, basic_json_t>::value, int> = 0 > basic_json get() const { return *this; } /*! @brief get a value (explicit) Explicit type conversion between the JSON value and a compatible value which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). The value is converted by calling the @ref json_serializer `from_json()` method. The function is equivalent to executing @code {.cpp} ValueType ret; JSONSerializer ::from_json(*this, ret); return ret; @endcode This overloads is chosen if: - @a ValueType is not @ref basic_json, - @ref json_serializer has a `from_json()` method of the form `void from_json(const @ref basic_json&, ValueType&)`, and - @ref json_serializer does not have a `from_json()` method of the form `ValueType from_json(const @ref basic_json&)` @tparam ValueTypeCV the provided value type @tparam ValueType the returned value type @return copy of the JSON value, converted to @a ValueType @throw what @ref json_serializer `from_json()` method throws @liveexample{The example below shows several conversions from JSON values to other types. There a few things to note: (1) Floating-point numbers can be converted to integers\, (2) A JSON array can be converted to a standard `std::vector `\, (3) A JSON object can be converted to C++ associative containers such as `std::unordered_map `.,get__ValueType_const} @since version 2.1.0 */ template < typename ValueTypeCV, typename ValueType = detail::uncvref_t , detail::enable_if_t < not std::is_same ::value and detail::has_from_json ::value and not detail::has_non_default_from_json ::value, int > = 0 > ValueType get() const noexcept(noexcept( JSONSerializer ::from_json(std::declval (), std::declval ()))) { // we cannot static_assert on ValueTypeCV being non-const, because // there is support for get (), which is why we // still need the uncvref static_assert(not std::is_reference ::value, "get() cannot be used with reference types, you might want to use get_ref()"); static_assert(std::is_default_constructible ::value, "types must be DefaultConstructible when used with get()"); ValueType ret; JSONSerializer ::from_json(*this, ret); return ret; } /*! @brief get a value (explicit); special case Explicit type conversion between the JSON value and a compatible value which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). The value is converted by calling the @ref json_serializer `from_json()` method. The function is equivalent to executing @code {.cpp} return JSONSerializer ::from_json(*this); @endcode This overloads is chosen if: - @a ValueType is not @ref basic_json and - @ref json_serializer has a `from_json()` method of the form `ValueType from_json(const @ref basic_json&)` @note If @ref json_serializer has both overloads of `from_json()`, this one is chosen. @tparam ValueTypeCV the provided value type @tparam ValueType the returned value type @return copy of the JSON value, converted to @a ValueType @throw what @ref json_serializer `from_json()` method throws @since version 2.1.0 */ template < typename ValueTypeCV, typename ValueType = detail::uncvref_t , detail::enable_if_t ::value and detail::has_non_default_from_json ::value, int> = 0 > ValueType get() const noexcept(noexcept( JSONSerializer ::from_json(std::declval ()))) { static_assert(not std::is_reference ::value, "get() cannot be used with reference types, you might want to use get_ref()"); return JSONSerializer ::from_json(*this); } /*! @brief get a pointer value (explicit) Explicit pointer access to the internally stored JSON value. No copies are made. @warning The pointer becomes invalid if the underlying JSON object changes. @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, @ref number_unsigned_t, or @ref number_float_t. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @complexity Constant. @liveexample{The example below shows how pointers to internal values of a JSON value can be requested. Note that no type conversions are made and a `nullptr` is returned if the value and the requested pointer type does not match.,get__PointerType} @sa @ref get_ptr() for explicit pointer-member access @since version 1.0.0 */ template ::value, int>::type = 0> PointerType get() noexcept { // delegate the call to get_ptr return get_ptr (); } /*! @brief get a pointer value (explicit) @copydoc get() */ template ::value, int>::type = 0> constexpr const PointerType get() const noexcept { // delegate the call to get_ptr return get_ptr (); } /*! @brief get a pointer value (implicit) Implicit pointer access to the internally stored JSON value. No copies are made. @warning Writing data to the pointee of the result yields an undefined state. @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, @ref number_unsigned_t, or @ref number_float_t. Enforced by a static assertion. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @complexity Constant. @liveexample{The example below shows how pointers to internal values of a JSON value can be requested. Note that no type conversions are made and a `nullptr` is returned if the value and the requested pointer type does not match.,get_ptr} @since version 1.0.0 */ template ::value, int>::type = 0> PointerType get_ptr() noexcept { // get the type of the PointerType (remove pointer and const) using pointee_t = typename std::remove_const ::type>::type>::type; // make sure the type matches the allowed types static_assert( std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value , "incompatible pointer type"); // delegate the call to get_impl_ptr<>() return get_impl_ptr(static_cast (nullptr)); } /*! @brief get a pointer value (implicit) @copydoc get_ptr() */ template ::value and std::is_const ::type>::value, int>::type = 0> constexpr const PointerType get_ptr() const noexcept { // get the type of the PointerType (remove pointer and const) using pointee_t = typename std::remove_const ::type>::type>::type; // make sure the type matches the allowed types static_assert( std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value , "incompatible pointer type"); // delegate the call to get_impl_ptr<>() const return get_impl_ptr(static_cast (nullptr)); } /*! @brief get a reference value (implicit) Implicit reference access to the internally stored JSON value. No copies are made. @warning Writing data to the referee of the result yields an undefined state. @tparam ReferenceType reference type; must be a reference to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref number_float_t. Enforced by static assertion. @return reference to the internally stored JSON value if the requested reference type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise @throw std::domain_error in case passed type @a ReferenceType is incompatible with the stored JSON value @complexity Constant. @liveexample{The example shows several calls to `get_ref()`.,get_ref} @since version 1.1.0 */ template ::value, int>::type = 0> ReferenceType get_ref() { // delegate call to get_ref_impl return get_ref_impl (*this); } /*! @brief get a reference value (implicit) @copydoc get_ref() */ template ::value and std::is_const ::type>::value, int>::type = 0> ReferenceType get_ref() const { // delegate call to get_ref_impl return get_ref_impl (*this); } /*! @brief get a value (implicit) Implicit type conversion between the JSON value and a compatible value. The call is realized by calling @ref get() const. @tparam ValueType non-pointer type compatible to the JSON value, for instance `int` for JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for JSON arrays. The character type of @ref string_t as well as an initializer list of this type is excluded to avoid ambiguities as these types implicitly convert to `std::string`. @return copy of the JSON value, converted to type @a ValueType @throw std::domain_error in case passed type @a ValueType is incompatible to JSON, thrown by @ref get() const @complexity Linear in the size of the JSON value. @liveexample{The example below shows several conversions from JSON values to other types. There a few things to note: (1) Floating-point numbers can be converted to integers\, (2) A JSON array can be converted to a standard `std::vector `\, (3) A JSON object can be converted to C++ associative containers such as `std::unordered_map `.,operator__ValueType} @since version 1.0.0 */ template < typename ValueType, typename std::enable_if < not std::is_pointer ::value and not std::is_same ::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same >::value #endif , int >::type = 0 > operator ValueType() const { // delegate the call to get<>() const return get (); } /// @} //////////////////// // element access // //////////////////// /// @name element access /// Access to the JSON value. /// @{ /*! @brief access specified array element with bounds checking Returns a reference to the element at specified location @a idx, with bounds checking. @param[in] idx index of the element to access @return reference to the element at index @a idx @throw std::domain_error if the JSON value is not an array; example: `"cannot use at() with string"` @throw std::out_of_range if the index @a idx is out of range of the array; that is, `idx >= size()`; example: `"array index 7 is out of range"` @complexity Constant. @liveexample{The example below shows how array elements can be read and written using `at()`.,at__size_type} @since version 1.0.0 */ reference at(size_type idx) { // at only works for arrays if (is_array()) { JSON_TRY { return m_value.array->at(idx); } JSON_CATCH (std::out_of_range&) { // create better exception explanation JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } } else { JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } []
operatorValueType()const
in /src/tinygltf/examples/validator/src/json.hpp:3492
[] void []
default_parse_context::parse_string
in /src/tinygltf/examples/common/picojson.h:878
['input '] bool []
default_parse_context::parse_array_item
in /src/tinygltf/examples/common/picojson.h:886
['input '] bool []
default_parse_context::parse_object_item
in /src/tinygltf/examples/common/picojson.h:897
['input ', 'std::string'] bool []

Sink functions/methods found for CWE20

Target sink Reached by fuzzer Function call path Possible branch blockers
get ['/src/tinygltf/tests/fuzzer/fuzz_gltf.cc'] N/A
Blocker function Arguments type Return type Constants touched
nlohmann::detail::lexer::scan_string
in /src/tinygltf/json.hpp:6874
[] token_type []
nlohmann::detail::lexer::scan_comment
in /src/tinygltf/json.hpp:7464
[] bool []
nlohmann::detail::lexer::scan_number
in /src/tinygltf/json.hpp:7589
[] token_type []
nlohmann::detail::parser::parser
in /src/tinygltf/json.hpp:10988
['InputAdapterType'] void []
operator""_json(constchar*s,std::size_tn)
in /src/tinygltf/examples/validator/src/json.hpp:12969
['char*', 'std::size_t'] nlohmann::json []
displayLoop
in /src/tinygltf/examples/basic/main.cpp:284
['Window', 'std::string'] void []
example::LoadGLTF
in /src/tinygltf/examples/raytrace/gltf-loader.cc:19
['std::string', 'float', 'std::vector >*', 'std::vector *', 'std::vector *'] bool []
main
in /src/tinygltf/examples/gltfutil/main.cc:133
['int', 'char*[]'] int []
JsonConstruct
in /src/tinygltf/tests/tester.cc:19
['char*'] tinygltf::detail::JsonDocument []
&operator>>(std::istream&is,picojson::value&x)
in /src/tinygltf/examples/common/picojson.h:1027
['std::istream', 'picojson::value'] std::istream []
example::LoadRenderConfig
in /src/tinygltf/examples/raytrace/render-config.cc:10
['example::RenderConfig*', 'char*'] bool []
parser::parse
in /src/tinygltf/examples/validator/src/json.hpp:11379
[] basic_json []
(3) boolsax_parse(constinput_format_tformat, json_sax_t*sax_, constboolstrict=true, constcbor_tag_handler_ttag_handler=cbor_tag_handler_t::error)
in /src/tinygltf/json.hpp:8484
['input_format_t', 'json_sax_t*'] JSON_HEDLEY_NON_NULL []
accept
in /src/tinygltf/json.hpp:24505
['detail::span_input_adapter'] bool []
nlohmann::detail::parser::accept
in /src/tinygltf/json.hpp:11070
[] bool []
from_ubjson
in /src/tinygltf/json.hpp:25536
['detail::span_input_adapter'] basic_json []
from_bson
in /src/tinygltf/json.hpp:25650
['detail::span_input_adapter'] basic_json []
operator[](UnpositionalTag)
in /src/tinygltf/tests/catch.hpp:4397
[] ArgBuilder []
Clara::CommandLine::parse
in /src/tinygltf/tests/catch.hpp:4485
['int', 'char*[]'] ConfigT []
Catch::TestCaseTracking::TrackerContext::startCycle
in /src/tinygltf/tests/catch.hpp:5516
[] void []
Catch::runTests
in /src/tinygltf/tests/catch.hpp:6231
['Ptr '] Totals []
Catch::DebugOutStream::DebugOutStream
in /src/tinygltf/tests/catch.hpp:6840
[] void []
TestCase::operator==(TestCaseconst&other)const
in /src/tinygltf/tests/catch.hpp:7463
['TestCase'] bool []
nlohmann::const_reference::at
in /src/tinygltf/examples/validator/src/json.hpp:1039
['size_type'] class basic_json { private: template friend struct detail::external_constructor; /// workaround type for MSVC using basic_json_t = basic_json ; public: using value_t = detail::value_t; // forward declarations template class iter_impl; template class json_reverse_iterator; class json_pointer; template using json_serializer = JSONSerializer ; ///////////////////// // container types // ///////////////////// /// @name container types /// The canonic container types to use @ref basic_json like any other STL /// container. /// @{ /// the type of elements in a basic_json container using value_type = basic_json; /// the type of an element reference using reference = value_type&; /// the type of an element const reference using const_reference = const value_type&; /// a type to represent differences between iterators using difference_type = std::ptrdiff_t; /// a type to represent container sizes using size_type = std::size_t; /// the allocator type using allocator_type = AllocatorType ; /// the type of an element pointer using pointer = typename std::allocator_traits ::pointer; /// the type of an element const pointer using const_pointer = typename std::allocator_traits ::const_pointer; /// an iterator for a basic_json container using iterator = iter_impl ; /// a const iterator for a basic_json container using const_iterator = iter_impl ; /// a reverse iterator for a basic_json container using reverse_iterator = json_reverse_iterator ; /// a const reverse iterator for a basic_json container using const_reverse_iterator = json_reverse_iterator ; /// @} /*! @brief returns the allocator associated with the container */ static allocator_type get_allocator() { return allocator_type(); } /*! @brief returns version information on the library This function returns a JSON object with information about the library, including the version number and information on the platform and compiler. @return JSON object holding version information key | description ----------- | --------------- `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). `copyright` | The copyright line for the library as string. `name` | The name of the library as string. `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. `url` | The URL of the project as string. `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). @liveexample{The following code shows an example output of the `meta()` function.,meta} @complexity Constant. @since 2.1.0 */ static basic_json meta() { basic_json result; result["copyright"] = "(C) 2013-2017 Niels Lohmann"; result["name"] = "JSON for Modern C++"; result["url"] = "https://github.com/nlohmann/json"; result["version"] = { {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, {"patch", 1} }; #ifdef _WIN32 result["platform"] = "win32"; #elif defined __linux__ result["platform"] = "linux"; #elif defined __APPLE__ result["platform"] = "apple"; #elif defined __unix__ result["platform"] = "unix"; #else result["platform"] = "unknown"; #endif #if defined(__clang__) result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; #elif defined(__ICC) || defined(__INTEL_COMPILER) result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; #elif defined(__GNUC__) || defined(__GNUG__) result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; #elif defined(__HP_cc) || defined(__HP_aCC) result["compiler"] = "hp" #elif defined(__IBMCPP__) result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; #elif defined(_MSC_VER) result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; #elif defined(__PGI) result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; #elif defined(__SUNPRO_CC) result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; #else result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; #endif #ifdef __cplusplus result["compiler"]["c++"] = std::to_string(__cplusplus); #else result["compiler"]["c++"] = "unknown"; #endif return result; } /////////////////////////// // JSON value data types // /////////////////////////// /// @name JSON value data types /// The data types to store a JSON value. These types are derived from /// the template arguments passed to class @ref basic_json. /// @{ /*! @brief a type for an object [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: > An object is an unordered collection of zero or more name/value pairs, > where a name is a string and a value is a string, number, boolean, null, > object, or array. To store objects in C++, a type is defined by the template parameters described below. @tparam ObjectType the container to store objects (e.g., `std::map` or `std::unordered_map`) @tparam StringType the type of the keys or names (e.g., `std::string`). The comparison function `std::less ` is used to order elements inside the container. @tparam AllocatorType the allocator to use for objects (e.g., `std::allocator`) #### Default type With the default values for @a ObjectType (`std::map`), @a StringType (`std::string`), and @a AllocatorType (`std::allocator`), the default value for @a object_t is: @code {.cpp} std::map< std::string, // key_type basic_json, // value_type std::less , // key_compare std::allocator > // allocator_type > @endcode #### Behavior The choice of @a object_t influences the behavior of the JSON class. With the default type, objects have the following behavior: - When all names are unique, objects will be interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings. - When the names within an object are not unique, later stored name/value pairs overwrite previously stored name/value pairs, leaving the used names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will be treated as equal and both stored as `{"key": 1}`. - Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see @ref dump) in this order. For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and serialized as `{"a": 2, "b": 1}`. - When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense that they will not be affected by these differences. For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be treated as equal. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the maximum depth of nesting. In this class, the object's limit of nesting is not constraint explicitly. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the @ref max_size function of a JSON object. #### Storage Objects are stored as pointers in a @ref basic_json type. That is, for any access to object values, a pointer of type `object_t*` must be dereferenced. @sa @ref array_t -- type for an array value @since version 1.0.0 @note The order name/value pairs are added to the object is *not* preserved by the library. Therefore, iterating an object may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to [RFC 7159](http://rfc7159.net/rfc7159), because any order implements the specified "unordered" nature of JSON objects. */ using object_t = ObjectType , AllocatorType >>; /*! @brief a type for an array [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: > An array is an ordered sequence of zero or more values. To store objects in C++, a type is defined by the template parameters explained below. @tparam ArrayType container type to store arrays (e.g., `std::vector` or `std::list`) @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) #### Default type With the default values for @a ArrayType (`std::vector`) and @a AllocatorType (`std::allocator`), the default value for @a array_t is: @code {.cpp} std::vector< basic_json, // value_type std::allocator // allocator_type > @endcode #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the maximum depth of nesting. In this class, the array's limit of nesting is not constraint explicitly. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the @ref max_size function of a JSON array. #### Storage Arrays are stored as pointers in a @ref basic_json type. That is, for any access to array values, a pointer of type `array_t*` must be dereferenced. @sa @ref object_t -- type for an object value @since version 1.0.0 */ using array_t = ArrayType >; /*! @brief a type for a string [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: > A string is a sequence of zero or more Unicode characters. To store objects in C++, a type is defined by the template parameter described below. Unicode values are split by the JSON class into byte-sized characters during deserialization. @tparam StringType the container to store strings (e.g., `std::string`). Note this container is used for keys/names in objects, see @ref object_t. #### Default type With the default values for @a StringType (`std::string`), the default value for @a string_t is: @code {.cpp} std::string @endcode #### Encoding Strings are stored in UTF-8 encoding. Therefore, functions like `std::string::size()` or `std::string::length()` return the number of bytes in the string rather than the number of characters or glyphs. #### String comparison [RFC 7159](http://rfc7159.net/rfc7159) states: > Software implementations are typically required to test names of object > members for equality. Implementations that transform the textual > representation into sequences of Unicode code units and then perform the > comparison numerically, code unit by code unit, are interoperable in the > sense that implementations will agree in all cases on equality or > inequality of two strings. For example, implementations that compare > strings with escaped characters unconverted may incorrectly find that > `"a\\b"` and `"a\u005Cb"` are not equal. This implementation is interoperable as it does compare strings code unit by code unit. #### Storage String values are stored as pointers in a @ref basic_json type. That is, for any access to string values, a pointer of type `string_t*` must be dereferenced. @since version 1.0.0 */ using string_t = StringType; /*! @brief a type for a boolean [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a type which differentiates the two literals `true` and `false`. To store objects in C++, a type is defined by the template parameter @a BooleanType which chooses the type to use. #### Default type With the default values for @a BooleanType (`bool`), the default value for @a boolean_t is: @code {.cpp} bool @endcode #### Storage Boolean values are stored directly inside a @ref basic_json type. @since version 1.0.0 */ using boolean_t = BooleanType; /*! @brief a type for a number (integer) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store integer numbers in C++, a type is defined by the template parameter @a NumberIntegerType which chooses the type to use. #### Default type With the default values for @a NumberIntegerType (`int64_t`), the default value for @a number_integer_t is: @code {.cpp} int64_t @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For instance, the C++ integer literal `010` will be serialized to `8`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the range and precision of numbers. When the default type is used, the maximal integer number that can be stored is `9223372036854775807` (INT64_MAX) and the minimal integer number that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as @ref number_unsigned_t or @ref number_float_t. [RFC 7159](http://rfc7159.net/rfc7159) further states: > Note that when such software is used, numbers that are integers and are > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense > that implementations will agree exactly on their numeric values. As this range is a subrange of the exactly supported range [INT64_MIN, INT64_MAX], this class's integer type is interoperable. #### Storage Integer number values are stored directly inside a @ref basic_json type. @sa @ref number_float_t -- type for number values (floating-point) @sa @ref number_unsigned_t -- type for number values (unsigned integer) @since version 1.0.0 */ using number_integer_t = NumberIntegerType; /*! @brief a type for a number (unsigned) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store unsigned integer numbers in C++, a type is defined by the template parameter @a NumberUnsignedType which chooses the type to use. #### Default type With the default values for @a NumberUnsignedType (`uint64_t`), the default value for @a number_unsigned_t is: @code {.cpp} uint64_t @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For instance, the C++ integer literal `010` will be serialized to `8`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) specifies: > An implementation may set limits on the range and precision of numbers. When the default type is used, the maximal integer number that can be stored is `18446744073709551615` (UINT64_MAX) and the minimal integer number that can be stored is `0`. Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as @ref number_integer_t or @ref number_float_t. [RFC 7159](http://rfc7159.net/rfc7159) further states: > Note that when such software is used, numbers that are integers and are > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the number_integer_t type) of the exactly supported range [0, UINT64_MAX], this class's integer type is interoperable. #### Storage Integer number values are stored directly inside a @ref basic_json type. @sa @ref number_float_t -- type for number values (floating-point) @sa @ref number_integer_t -- type for number values (integer) @since version 2.0.0 */ using number_unsigned_t = NumberUnsignedType; /*! @brief a type for a number (floating-point) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: > The representation of numbers is similar to that used in most > programming languages. A number is represented in base 10 using decimal > digits. It contains an integer component that may be prefixed with an > optional minus sign, which may be followed by a fraction part and/or an > exponent part. Leading zeros are not allowed. (...) Numeric values that > cannot be represented in the grammar below (such as Infinity and NaN) > are not permitted. This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, @ref number_integer_t, @ref number_unsigned_t and @ref number_float_t are used. To store floating-point numbers in C++, a type is defined by the template parameter @a NumberFloatType which chooses the type to use. #### Default type With the default values for @a NumberFloatType (`double`), the default value for @a number_float_t is: @code {.cpp} double @endcode #### Default behavior - The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in floating-point literals will be ignored. Internally, the value will be stored as decimal number. For instance, the C++ floating-point literal `01.2` will be serialized to `1.2`. During deserialization, leading zeros yield an error. - Not-a-number (NaN) values will be serialized to `null`. #### Limits [RFC 7159](http://rfc7159.net/rfc7159) states: > This specification allows implementations to set limits on the range and > precision of numbers accepted. Since software that implements IEEE > 754-2008 binary64 (double precision) numbers is generally available and > widely used, good interoperability can be achieved by implementations > that expect no more precision or range than these provide, in the sense > that implementations will approximate JSON numbers within the expected > precision. This implementation does exactly follow this approach, as it uses double precision floating-point numbers. Note values smaller than `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` will be stored as NaN internally and be serialized to `null`. #### Storage Floating-point number values are stored directly inside a @ref basic_json type. @sa @ref number_integer_t -- type for number values (integer) @sa @ref number_unsigned_t -- type for number values (unsigned integer) @since version 1.0.0 */ using number_float_t = NumberFloatType; /// @} private: /// helper for exception-safe object creation template static T* create(Args&& ... args) { AllocatorType alloc; auto deleter = [&](T * object) { alloc.deallocate(object, 1); }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward (args)...); assert(object != nullptr); return object.release(); } //////////////////////// // JSON value storage // //////////////////////// /*! @brief a JSON value The actual storage for a JSON value of the @ref basic_json class. This union combines the different storage types for the JSON value types defined in @ref value_t. JSON type | value_t type | used type --------- | --------------- | ------------------------ object | object | pointer to @ref object_t array | array | pointer to @ref array_t string | string | pointer to @ref string_t boolean | boolean | @ref boolean_t number | number_integer | @ref number_integer_t number | number_unsigned | @ref number_unsigned_t number | number_float | @ref number_float_t null | null | *no value is stored* @note Variable-length types (objects, arrays, and strings) are stored as pointers. The size of the union should not exceed 64 bits if the default value types are used. @since version 1.0.0 */ union json_value { /// object (stored with pointer to save storage) object_t* object; /// array (stored with pointer to save storage) array_t* array; /// string (stored with pointer to save storage) string_t* string; /// boolean boolean_t boolean; /// number (integer) number_integer_t number_integer; /// number (unsigned integer) number_unsigned_t number_unsigned; /// number (floating-point) number_float_t number_float; /// default constructor (for null values) json_value() = default; /// constructor for booleans json_value(boolean_t v) noexcept : boolean(v) {} /// constructor for numbers (integer) json_value(number_integer_t v) noexcept : number_integer(v) {} /// constructor for numbers (unsigned) json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} /// constructor for numbers (floating-point) json_value(number_float_t v) noexcept : number_float(v) {} /// constructor for empty values of a given type json_value(value_t t) { switch (t) { case value_t::object: { object = create (); break; } case value_t::array: { array = create (); break; } case value_t::string: { string = create (""); break; } case value_t::boolean: { boolean = boolean_t(false); break; } case value_t::number_integer: { number_integer = number_integer_t(0); break; } case value_t::number_unsigned: { number_unsigned = number_unsigned_t(0); break; } case value_t::number_float: { number_float = number_float_t(0.0); break; } case value_t::null: { break; } default: { if (t == value_t::null) { JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE } break; } } } /// constructor for strings json_value(const string_t& value) { string = create (value); } /// constructor for objects json_value(const object_t& value) { object = create (value); } /// constructor for arrays json_value(const array_t& value) { array = create (value); } }; /*! @brief checks the class invariants This function asserts the class invariants. It needs to be called at the end of every constructor to make sure that created objects respect the invariant. Furthermore, it has to be called each time the type of a JSON value is changed, because the invariant expresses a relationship between @a m_type and @a m_value. */ void assert_invariant() const { assert(m_type != value_t::object or m_value.object != nullptr); assert(m_type != value_t::array or m_value.array != nullptr); assert(m_type != value_t::string or m_value.string != nullptr); } public: ////////////////////////// // JSON parser callback // ////////////////////////// /*! @brief JSON callback events This enumeration lists the parser events that can trigger calling a callback function of type @ref parser_callback_t during parsing. @image html callback_events.png "Example when certain parse events are triggered" @since version 1.0.0 */ enum class parse_event_t : uint8_t { /// the parser read `{` and started to process a JSON object object_start, /// the parser read `}` and finished processing a JSON object object_end, /// the parser read `[` and started to process a JSON array array_start, /// the parser read `]` and finished processing a JSON array array_end, /// the parser read a key of a value in an object key, /// the parser finished reading a JSON value value }; /*! @brief per-element parser callback type With a parser callback function, the result of parsing a JSON text can be influenced. When passed to @ref parse(std::istream&, const parser_callback_t) or @ref parse(const CharT, const parser_callback_t), it is called on certain events (passed as @ref parse_event_t via parameter @a event) with a set recursion depth @a depth and context JSON value @a parsed. The return value of the callback function is a boolean indicating whether the element that emitted the callback shall be kept or not. We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values of the parameters @a depth, @a event, and @a parsed. parameter @a event | description | parameter @a depth | parameter @a parsed ------------------ | ----------- | ------------------ | ------------------- parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value @image html callback_events.png "Example when certain parse events are triggered" Discarding a value (i.e., returning `false`) has different effects depending on the context in which function was called: - Discarded values in structured types are skipped. That is, the parser will behave as if the discarded value was never read. - In case a value outside a structured type is skipped, it is replaced with `null`. This case happens if the top-level element is skipped. @param[in] depth the depth of the recursion during parsing @param[in] event an event of type parse_event_t indicating the context in the callback function has been called @param[in,out] parsed the current intermediate parse result; note that writing to this value has no effect for parse_event_t::key events @return Whether the JSON value which called the function during parsing should be kept (`true`) or not (`false`). In the latter case, it is either skipped completely or replaced by an empty discarded object. @sa @ref parse(std::istream&, parser_callback_t) or @ref parse(const CharT, const parser_callback_t) for examples @since version 1.0.0 */ using parser_callback_t = std::function ; ////////////////// // constructors // ////////////////// /// @name constructors and destructors /// Constructors of class @ref basic_json, copy/move constructor, copy /// assignment, static functions creating objects, and the destructor. /// @{ /*! @brief create an empty value with a given type Create an empty JSON value with a given type. The value will be default initialized with an empty value which depends on the type: Value type | initial value ----------- | ------------- null | `null` boolean | `false` string | `""` number | `0` object | `{}` array | `[]` @param[in] value_type the type of the value to create @complexity Constant. @throw std::bad_alloc if allocation for object, array, or string value fails @liveexample{The following code shows the constructor for different @ref value_t values,basic_json__value_t} @since version 1.0.0 */ basic_json(const value_t value_type) : m_type(value_type), m_value(value_type) { assert_invariant(); } /*! @brief create a null object Create a `null` JSON value. It either takes a null pointer as parameter (explicitly creating `null`) or no parameter (implicitly creating `null`). The passed null pointer itself is not read -- it is only used to choose the right constructor. @complexity Constant. @exceptionsafety No-throw guarantee: this constructor never throws exceptions. @liveexample{The following code shows the constructor with and without a null pointer parameter.,basic_json__nullptr_t} @since version 1.0.0 */ basic_json(std::nullptr_t = nullptr) noexcept : basic_json(value_t::null) { assert_invariant(); } /*! @brief create a JSON value This is a "catch all" constructor for all compatible JSON types; that is, types for which a `to_json()` method exsits. The constructor forwards the parameter @a val to that method (to `json_serializer ::to_json` method with `U = uncvref_t `, to be exact). Template type @a CompatibleType includes, but is not limited to, the following types: - **arrays**: @ref array_t and all kinds of compatible containers such as `std::vector`, `std::deque`, `std::list`, `std::forward_list`, `std::array`, `std::set`, `std::unordered_set`, `std::multiset`, and `unordered_multiset` with a `value_type` from which a @ref basic_json value can be constructed. - **objects**: @ref object_t and all kinds of compatible associative containers such as `std::map`, `std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with a `key_type` compatible to @ref string_t and a `value_type` from which a @ref basic_json value can be constructed. - **strings**: @ref string_t, string literals, and all compatible string containers can be used. - **numbers**: @ref number_integer_t, @ref number_unsigned_t, @ref number_float_t, and all convertible number types such as `int`, `size_t`, `int64_t`, `float` or `double` can be used. - **boolean**: @ref boolean_t / `bool` can be used. See the examples below. @tparam CompatibleType a type such that: - @a CompatibleType is not derived from `std::istream`, - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move constructors), - @a CompatibleType is not a @ref basic_json nested type (e.g., @ref json_pointer, @ref iterator, etc ...) - @ref @ref json_serializer has a `to_json(basic_json_t&, CompatibleType&&)` method @tparam U = `uncvref_t ` @param[in] val the value to be forwarded @complexity Usually linear in the size of the passed @a val, also depending on the implementation of the called `to_json()` method. @throw what `json_serializer ::to_json()` throws @liveexample{The following code shows the constructor with several compatible types.,basic_json__CompatibleType} @since version 2.1.0 */ template , detail::enable_if_t ::value and not std::is_same ::value and not detail::is_basic_json_nested_type< basic_json_t, U>::value and detail::has_to_json ::value, int> = 0> basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer ::to_json( std::declval (), std::forward (val)))) { JSONSerializer ::to_json(*this, std::forward (val)); assert_invariant(); } /*! @brief create a container (array or object) from an initializer list Creates a JSON value of type array or object from the passed initializer list @a init. In case @a type_deduction is `true` (default), the type of the JSON value to be created is deducted from the initializer list @a init according to the following rules: 1. If the list is empty, an empty JSON object value `{}` is created. 2. If the list consists of pairs whose first element is a string, a JSON object value is created where the first elements of the pairs are treated as keys and the second elements are as values. 3. In all other cases, an array is created. The rules aim to create the best fit between a C++ initializer list and JSON values. The rationale is as follows: 1. The empty initializer list is written as `{}` which is exactly an empty JSON object. 2. C++ has now way of describing mapped types other than to list a list of pairs. As JSON requires that keys must be of type string, rule 2 is the weakest constraint one can pose on initializer lists to interpret them as an object. 3. In all other cases, the initializer list could not be interpreted as JSON object type, so interpreting it as JSON array type is safe. With the rules described above, the following JSON values cannot be expressed by an initializer list: - the empty array (`[]`): use @ref array(std::initializer_list ) with an empty initializer list in this case - arrays whose elements satisfy rule 2: use @ref array(std::initializer_list ) with the same initializer list in this case @note When used without parentheses around an empty initializer list, @ref basic_json() is called instead of this function, yielding the JSON null value. @param[in] init initializer list with JSON values @param[in] type_deduction internal parameter; when set to `true`, the type of the JSON value is deducted from the initializer list @a init; when set to `false`, the type provided via @a manual_type is forced. This mode is used by the functions @ref array(std::initializer_list ) and @ref object(std::initializer_list ). @param[in] manual_type internal parameter; when @a type_deduction is set to `false`, the created JSON value will use the provided type (only @ref value_t::array and @ref value_t::object are valid); when @a type_deduction is set to `true`, this parameter has no effect @throw std::domain_error if @a type_deduction is `false`, @a manual_type is `value_t::object`, but @a init contains an element which is not a pair whose first element is a string; example: `"cannot create object from initializer list"` @complexity Linear in the size of the initializer list @a init. @liveexample{The example below shows how JSON values are created from initializer lists.,basic_json__list_init_t} @sa @ref array(std::initializer_list ) -- create a JSON array value from an initializer list @sa @ref object(std::initializer_list ) -- create a JSON object value from an initializer list @since version 1.0.0 */ basic_json(std::initializer_list init, bool type_deduction = true, value_t manual_type = value_t::array) { // check if each element is an array with two elements whose first // element is a string bool is_an_object = std::all_of(init.begin(), init.end(), [](const basic_json & element) { return element.is_array() and element.size() == 2 and element[0].is_string(); }); // adjust type if type deduction is not wanted if (not type_deduction) { // if array is wanted, do not create an object though possible if (manual_type == value_t::array) { is_an_object = false; } // if object is wanted but impossible, throw an exception if (manual_type == value_t::object and not is_an_object) { JSON_THROW(std::domain_error("cannot create object from initializer list")); } } if (is_an_object) { // the initializer list is a list of pairs -> create object m_type = value_t::object; m_value = value_t::object; std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); }); } else { // the initializer list describes an array -> create array m_type = value_t::array; m_value.array = create (init); } assert_invariant(); } /*! @brief explicitly create an array from an initializer list Creates a JSON array value from a given initializer list. That is, given a list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the initializer list is empty, the empty array `[]` is created. @note This function is only needed to express two edge cases that cannot be realized with the initializer list constructor (@ref basic_json(std::initializer_list , bool, value_t)). These cases are: 1. creating an array whose elements are all pairs whose first element is a string -- in this case, the initializer list constructor would create an object, taking the first elements as keys 2. creating an empty array -- passing the empty initializer list to the initializer list constructor yields an empty object @param[in] init initializer list with JSON values to create an array from (optional) @return JSON array value @complexity Linear in the size of @a init. @liveexample{The following code shows an example for the `array` function.,array} @sa @ref basic_json(std::initializer_list , bool, value_t) -- create a JSON value from an initializer list @sa @ref object(std::initializer_list ) -- create a JSON object value from an initializer list @since version 1.0.0 */ static basic_json array(std::initializer_list init = std::initializer_list ()) { return basic_json(init, false, value_t::array); } /*! @brief explicitly create an object from an initializer list Creates a JSON object value from a given initializer list. The initializer lists elements must be pairs, and their first elements must be strings. If the initializer list is empty, the empty object `{}` is created. @note This function is only added for symmetry reasons. In contrast to the related function @ref array(std::initializer_list ), there are no cases which can only be expressed by this function. That is, any initializer list @a init can also be passed to the initializer list constructor @ref basic_json(std::initializer_list , bool, value_t). @param[in] init initializer list to create an object from (optional) @return JSON object value @throw std::domain_error if @a init is not a pair whose first elements are strings; thrown by @ref basic_json(std::initializer_list , bool, value_t) @complexity Linear in the size of @a init. @liveexample{The following code shows an example for the `object` function.,object} @sa @ref basic_json(std::initializer_list , bool, value_t) -- create a JSON value from an initializer list @sa @ref array(std::initializer_list ) -- create a JSON array value from an initializer list @since version 1.0.0 */ static basic_json object(std::initializer_list init = std::initializer_list ()) { return basic_json(init, false, value_t::object); } /*! @brief construct an array with count copies of given value Constructs a JSON array value by creating @a cnt copies of a passed value. In case @a cnt is `0`, an empty array is created. As postcondition, `std::distance(begin(),end()) == cnt` holds. @param[in] cnt the number of JSON copies of @a val to create @param[in] val the JSON value to copy @complexity Linear in @a cnt. @liveexample{The following code shows examples for the @ref basic_json(size_type\, const basic_json&) constructor.,basic_json__size_type_basic_json} @since version 1.0.0 */ basic_json(size_type cnt, const basic_json& val) : m_type(value_t::array) { m_value.array = create (cnt, val); assert_invariant(); } /*! @brief construct a JSON container given an iterator range Constructs the JSON value with the contents of the range `[first, last)`. The semantics depends on the different types a JSON value can have: - In case of primitive types (number, boolean, or string), @a first must be `begin()` and @a last must be `end()`. In this case, the value is copied. Otherwise, std::out_of_range is thrown. - In case of structured types (array, object), the constructor behaves as similar versions for `std::vector`. - In case of a null type, std::domain_error is thrown. @tparam InputIT an input iterator type (@ref iterator or @ref const_iterator) @param[in] first begin of the range to copy from (included) @param[in] last end of the range to copy from (excluded) @pre Iterators @a first and @a last must be initialized. **This precondition is enforced with an assertion.** @throw std::domain_error if iterators are not compatible; that is, do not belong to the same JSON value; example: `"iterators are not compatible"` @throw std::out_of_range if iterators are for a primitive type (number, boolean, or string) where an out of range error can be detected easily; example: `"iterators out of range"` @throw std::bad_alloc if allocation for object, array, or string fails @throw std::domain_error if called with a null value; example: `"cannot use construct with iterators from null"` @complexity Linear in distance between @a first and @a last. @liveexample{The example below shows several ways to create JSON values by specifying a subrange with iterators.,basic_json__InputIt_InputIt} @since version 1.0.0 */ template ::value or std::is_same ::value, int>::type = 0> basic_json(InputIT first, InputIT last) { assert(first.m_object != nullptr); assert(last.m_object != nullptr); // make sure iterator fits the current value if (first.m_object != last.m_object) { JSON_THROW(std::domain_error("iterators are not compatible")); } // copy type from first iterator m_type = first.m_object->m_type; // check if iterator range is complete for primitive values switch (m_type) { case value_t::boolean: case value_t::number_float: case value_t::number_integer: case value_t::number_unsigned: case value_t::string: { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { JSON_THROW(std::out_of_range("iterators out of range")); } break; } default: { break; } } switch (m_type) { case value_t::number_integer: { m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { m_value = *first.m_object->m_value.string; break; } case value_t::object: { m_value.object = create (first.m_it.object_iterator, last.m_it.object_iterator); break; } case value_t::array: { m_value.array = create (first.m_it.array_iterator, last.m_it.array_iterator); break; } default: { JSON_THROW(std::domain_error("cannot use construct with iterators from " + first.m_object->type_name())); } } assert_invariant(); } /*! @brief construct a JSON value given an input stream @param[in,out] i stream to read a serialized JSON value from @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @note A UTF-8 byte order mark is silently ignored. @deprecated This constructor is deprecated and will be removed in version 3.0.0 to unify the interface of the library. Deserialization will be done by stream operators or by calling one of the `parse` functions, e.g. @ref parse(std::istream&, const parser_callback_t). That is, calls like `json j(i);` for an input stream @a i need to be replaced by `json j = json::parse(i);`. See the example below. @liveexample{The example below demonstrates constructing a JSON value from a `std::stringstream` with and without callback function.,basic_json__istream} @since version 2.0.0, deprecated in version 2.0.3, to be removed in version 3.0.0 */ JSON_DEPRECATED explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) { *this = parser(i, cb).parse(); assert_invariant(); } /////////////////////////////////////// // other constructors and destructor // /////////////////////////////////////// /*! @brief copy constructor Creates a copy of a given JSON value. @param[in] other the JSON value to copy @complexity Linear in the size of @a other. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. - As postcondition, it holds: `other == basic_json(other)`. @throw std::bad_alloc if allocation for object, array, or string fails. @liveexample{The following code shows an example for the copy constructor.,basic_json__basic_json} @since version 1.0.0 */ basic_json(const basic_json& other) : m_type(other.m_type) { // check of passed value is valid other.assert_invariant(); switch (m_type) { case value_t::object: { m_value = *other.m_value.object; break; } case value_t::array: { m_value = *other.m_value.array; break; } case value_t::string: { m_value = *other.m_value.string; break; } case value_t::boolean: { m_value = other.m_value.boolean; break; } case value_t::number_integer: { m_value = other.m_value.number_integer; break; } case value_t::number_unsigned: { m_value = other.m_value.number_unsigned; break; } case value_t::number_float: { m_value = other.m_value.number_float; break; } default: { break; } } assert_invariant(); } /*! @brief move constructor Move constructor. Constructs a JSON value with the contents of the given value @a other using move semantics. It "steals" the resources from @a other and leaves it as JSON null value. @param[in,out] other value to move to this object @post @a other is a JSON null value @complexity Constant. @liveexample{The code below shows the move constructor explicitly called via std::move.,basic_json__moveconstructor} @since version 1.0.0 */ basic_json(basic_json&& other) noexcept : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) { // check that passed value is valid other.assert_invariant(); // invalidate payload other.m_type = value_t::null; other.m_value = {}; assert_invariant(); } /*! @brief copy assignment Copy assignment operator. Copies a JSON value via the "copy and swap" strategy: It is expressed in terms of the copy constructor, destructor, and the swap() member function. @param[in] other value to copy from @complexity Linear. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. @liveexample{The code below shows and example for the copy assignment. It creates a copy of value `a` which is then swapped with `b`. Finally\, the copy of `a` (which is the null value after the swap) is destroyed.,basic_json__copyassignment} @since version 1.0.0 */ reference& operator=(basic_json other) noexcept ( std::is_nothrow_move_constructible ::value and std::is_nothrow_move_assignable ::value and std::is_nothrow_move_constructible ::value and std::is_nothrow_move_assignable ::value ) { // check that passed value is valid other.assert_invariant(); using std::swap; swap(m_type, other.m_type); swap(m_value, other.m_value); assert_invariant(); return *this; } /*! @brief destructor Destroys the JSON value and frees all allocated memory. @complexity Linear. @requirement This function helps `basic_json` satisfying the [Container](http://en.cppreference.com/w/cpp/concept/Container) requirements: - The complexity is linear. - All stored elements are destroyed and all memory is freed. @since version 1.0.0 */ ~basic_json() { assert_invariant(); switch (m_type) { case value_t::object: { AllocatorType alloc; alloc.destroy(m_value.object); alloc.deallocate(m_value.object, 1); break; } case value_t::array: { AllocatorType alloc; alloc.destroy(m_value.array); alloc.deallocate(m_value.array, 1); break; } case value_t::string: { AllocatorType alloc; alloc.destroy(m_value.string); alloc.deallocate(m_value.string, 1); break; } default: { // all other types need no specific destructor break; } } } /// @} public: /////////////////////// // object inspection // /////////////////////// /// @name object inspection /// Functions to inspect the type of a JSON value. /// @{ /*! @brief serialization Serialization function for JSON values. The function tries to mimic Python's `json.dumps()` function, and currently supports its @a indent parameter. @param[in] indent If indent is nonnegative, then array elements and object members will be pretty-printed with that indent level. An indent level of `0` will only insert newlines. `-1` (the default) selects the most compact representation. @return string containing the serialization of the JSON value @complexity Linear. @liveexample{The following example shows the effect of different @a indent parameters to the result of the serialization.,dump} @see https://docs.python.org/2/library/json.html#json.dump @since version 1.0.0 */ string_t dump(const int indent = -1) const { std::stringstream ss; if (indent >= 0) { dump(ss, true, static_cast (indent)); } else { dump(ss, false, 0); } return ss.str(); } /*! @brief return the type of the JSON value (explicit) Return the type of the JSON value as a value from the @ref value_t enumeration. @return the type of the JSON value @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `type()` for all JSON types.,type} @since version 1.0.0 */ constexpr value_t type() const noexcept { return m_type; } /*! @brief return whether type is primitive This function returns true iff the JSON type is primitive (string, number, boolean, or null). @return `true` if type is primitive (string, number, boolean, or null), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_primitive()` for all JSON types.,is_primitive} @sa @ref is_structured() -- returns whether JSON value is structured @sa @ref is_null() -- returns whether JSON value is `null` @sa @ref is_string() -- returns whether JSON value is a string @sa @ref is_boolean() -- returns whether JSON value is a boolean @sa @ref is_number() -- returns whether JSON value is a number @since version 1.0.0 */ constexpr bool is_primitive() const noexcept { return is_null() or is_string() or is_boolean() or is_number(); } /*! @brief return whether type is structured This function returns true iff the JSON type is structured (array or object). @return `true` if type is structured (array or object), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_structured()` for all JSON types.,is_structured} @sa @ref is_primitive() -- returns whether value is primitive @sa @ref is_array() -- returns whether value is an array @sa @ref is_object() -- returns whether value is an object @since version 1.0.0 */ constexpr bool is_structured() const noexcept { return is_array() or is_object(); } /*! @brief return whether value is null This function returns true iff the JSON value is null. @return `true` if type is null, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_null()` for all JSON types.,is_null} @since version 1.0.0 */ constexpr bool is_null() const noexcept { return m_type == value_t::null; } /*! @brief return whether value is a boolean This function returns true iff the JSON value is a boolean. @return `true` if type is boolean, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_boolean()` for all JSON types.,is_boolean} @since version 1.0.0 */ constexpr bool is_boolean() const noexcept { return m_type == value_t::boolean; } /*! @brief return whether value is a number This function returns true iff the JSON value is a number. This includes both integer and floating-point values. @return `true` if type is number (regardless whether integer, unsigned integer or floating-type), `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number()` for all JSON types.,is_number} @sa @ref is_number_integer() -- check if value is an integer or unsigned integer number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 1.0.0 */ constexpr bool is_number() const noexcept { return is_number_integer() or is_number_float(); } /*! @brief return whether value is an integer number This function returns true iff the JSON value is an integer or unsigned integer number. This excludes floating-point values. @return `true` if type is an integer or unsigned integer number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_integer()` for all JSON types.,is_number_integer} @sa @ref is_number() -- check if value is a number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 1.0.0 */ constexpr bool is_number_integer() const noexcept { return m_type == value_t::number_integer or m_type == value_t::number_unsigned; } /*! @brief return whether value is an unsigned integer number This function returns true iff the JSON value is an unsigned integer number. This excludes floating-point and (signed) integer values. @return `true` if type is an unsigned integer number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_unsigned()` for all JSON types.,is_number_unsigned} @sa @ref is_number() -- check if value is a number @sa @ref is_number_integer() -- check if value is an integer or unsigned integer number @sa @ref is_number_float() -- check if value is a floating-point number @since version 2.0.0 */ constexpr bool is_number_unsigned() const noexcept { return m_type == value_t::number_unsigned; } /*! @brief return whether value is a floating-point number This function returns true iff the JSON value is a floating-point number. This excludes integer and unsigned integer values. @return `true` if type is a floating-point number, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_number_float()` for all JSON types.,is_number_float} @sa @ref is_number() -- check if value is number @sa @ref is_number_integer() -- check if value is an integer number @sa @ref is_number_unsigned() -- check if value is an unsigned integer number @since version 1.0.0 */ constexpr bool is_number_float() const noexcept { return m_type == value_t::number_float; } /*! @brief return whether value is an object This function returns true iff the JSON value is an object. @return `true` if type is object, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_object()` for all JSON types.,is_object} @since version 1.0.0 */ constexpr bool is_object() const noexcept { return m_type == value_t::object; } /*! @brief return whether value is an array This function returns true iff the JSON value is an array. @return `true` if type is array, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_array()` for all JSON types.,is_array} @since version 1.0.0 */ constexpr bool is_array() const noexcept { return m_type == value_t::array; } /*! @brief return whether value is a string This function returns true iff the JSON value is a string. @return `true` if type is string, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_string()` for all JSON types.,is_string} @since version 1.0.0 */ constexpr bool is_string() const noexcept { return m_type == value_t::string; } /*! @brief return whether value is discarded This function returns true iff the JSON value was discarded during parsing with a callback function (see @ref parser_callback_t). @note This function will always be `false` for JSON values after parsing. That is, discarded values can only occur during parsing, but will be removed when inside a structured value or replaced by null in other cases. @return `true` if type is discarded, `false` otherwise. @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies `is_discarded()` for all JSON types.,is_discarded} @since version 1.0.0 */ constexpr bool is_discarded() const noexcept { return m_type == value_t::discarded; } /*! @brief return the type of the JSON value (implicit) Implicitly return the type of the JSON value as a value from the @ref value_t enumeration. @return the type of the JSON value @complexity Constant. @exceptionsafety No-throw guarantee: this member function never throws exceptions. @liveexample{The following code exemplifies the @ref value_t operator for all JSON types.,operator__value_t} @since version 1.0.0 */ constexpr operator value_t() const noexcept { return m_type; } /// @} private: ////////////////// // value access // ////////////////// /// get a boolean (explicit) boolean_t get_impl(boolean_t* /*unused*/) const { if (is_boolean()) { return m_value.boolean; } JSON_THROW(std::domain_error("type must be boolean, but is " + type_name())); } /// get a pointer to the value (object) object_t* get_impl_ptr(object_t* /*unused*/) noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (array) array_t* get_impl_ptr(array_t* /*unused*/) noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (string) string_t* get_impl_ptr(string_t* /*unused*/) noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (boolean) boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /*! @brief helper function to implement get_ref() This funcion helps to implement get_ref() without code duplication for const and non-const overloads @tparam ThisType will be deduced as `basic_json` or `const basic_json` @throw std::domain_error if ReferenceType does not match underlying value type of the current JSON */ template static ReferenceType get_ref_impl(ThisType& obj) { // helper type using PointerType = typename std::add_pointer ::type; // delegate the call to get_ptr<>() auto ptr = obj.template get_ptr (); if (ptr != nullptr) { return *ptr; } JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " + obj.type_name())); } public: /// @name value access /// Direct access to the stored value of a JSON value. /// @{ /*! @brief get special-case overload This overloads avoids a lot of template boilerplate, it can be seen as the identity method @tparam BasicJsonType == @ref basic_json @return a copy of *this @complexity Constant. @since version 2.1.0 */ template < typename BasicJsonType, detail::enable_if_t ::type, basic_json_t>::value, int> = 0 > basic_json get() const { return *this; } /*! @brief get a value (explicit) Explicit type conversion between the JSON value and a compatible value which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). The value is converted by calling the @ref json_serializer `from_json()` method. The function is equivalent to executing @code {.cpp} ValueType ret; JSONSerializer ::from_json(*this, ret); return ret; @endcode This overloads is chosen if: - @a ValueType is not @ref basic_json, - @ref json_serializer has a `from_json()` method of the form `void from_json(const @ref basic_json&, ValueType&)`, and - @ref json_serializer does not have a `from_json()` method of the form `ValueType from_json(const @ref basic_json&)` @tparam ValueTypeCV the provided value type @tparam ValueType the returned value type @return copy of the JSON value, converted to @a ValueType @throw what @ref json_serializer `from_json()` method throws @liveexample{The example below shows several conversions from JSON values to other types. There a few things to note: (1) Floating-point numbers can be converted to integers\, (2) A JSON array can be converted to a standard `std::vector `\, (3) A JSON object can be converted to C++ associative containers such as `std::unordered_map `.,get__ValueType_const} @since version 2.1.0 */ template < typename ValueTypeCV, typename ValueType = detail::uncvref_t , detail::enable_if_t < not std::is_same ::value and detail::has_from_json ::value and not detail::has_non_default_from_json ::value, int > = 0 > ValueType get() const noexcept(noexcept( JSONSerializer ::from_json(std::declval (), std::declval ()))) { // we cannot static_assert on ValueTypeCV being non-const, because // there is support for get (), which is why we // still need the uncvref static_assert(not std::is_reference ::value, "get() cannot be used with reference types, you might want to use get_ref()"); static_assert(std::is_default_constructible ::value, "types must be DefaultConstructible when used with get()"); ValueType ret; JSONSerializer ::from_json(*this, ret); return ret; } /*! @brief get a value (explicit); special case Explicit type conversion between the JSON value and a compatible value which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). The value is converted by calling the @ref json_serializer `from_json()` method. The function is equivalent to executing @code {.cpp} return JSONSerializer ::from_json(*this); @endcode This overloads is chosen if: - @a ValueType is not @ref basic_json and - @ref json_serializer has a `from_json()` method of the form `ValueType from_json(const @ref basic_json&)` @note If @ref json_serializer has both overloads of `from_json()`, this one is chosen. @tparam ValueTypeCV the provided value type @tparam ValueType the returned value type @return copy of the JSON value, converted to @a ValueType @throw what @ref json_serializer `from_json()` method throws @since version 2.1.0 */ template < typename ValueTypeCV, typename ValueType = detail::uncvref_t , detail::enable_if_t ::value and detail::has_non_default_from_json ::value, int> = 0 > ValueType get() const noexcept(noexcept( JSONSerializer ::from_json(std::declval ()))) { static_assert(not std::is_reference ::value, "get() cannot be used with reference types, you might want to use get_ref()"); return JSONSerializer ::from_json(*this); } /*! @brief get a pointer value (explicit) Explicit pointer access to the internally stored JSON value. No copies are made. @warning The pointer becomes invalid if the underlying JSON object changes. @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, @ref number_unsigned_t, or @ref number_float_t. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @complexity Constant. @liveexample{The example below shows how pointers to internal values of a JSON value can be requested. Note that no type conversions are made and a `nullptr` is returned if the value and the requested pointer type does not match.,get__PointerType} @sa @ref get_ptr() for explicit pointer-member access @since version 1.0.0 */ template ::value, int>::type = 0> PointerType get() noexcept { // delegate the call to get_ptr return get_ptr (); } /*! @brief get a pointer value (explicit) @copydoc get() */ template ::value, int>::type = 0> constexpr const PointerType get() const noexcept { // delegate the call to get_ptr return get_ptr (); } /*! @brief get a pointer value (implicit) Implicit pointer access to the internally stored JSON value. No copies are made. @warning Writing data to the pointee of the result yields an undefined state. @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, @ref number_unsigned_t, or @ref number_float_t. Enforced by a static assertion. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @complexity Constant. @liveexample{The example below shows how pointers to internal values of a JSON value can be requested. Note that no type conversions are made and a `nullptr` is returned if the value and the requested pointer type does not match.,get_ptr} @since version 1.0.0 */ template ::value, int>::type = 0> PointerType get_ptr() noexcept { // get the type of the PointerType (remove pointer and const) using pointee_t = typename std::remove_const ::type>::type>::type; // make sure the type matches the allowed types static_assert( std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value , "incompatible pointer type"); // delegate the call to get_impl_ptr<>() return get_impl_ptr(static_cast (nullptr)); } /*! @brief get a pointer value (implicit) @copydoc get_ptr() */ template ::value and std::is_const ::type>::value, int>::type = 0> constexpr const PointerType get_ptr() const noexcept { // get the type of the PointerType (remove pointer and const) using pointee_t = typename std::remove_const ::type>::type>::type; // make sure the type matches the allowed types static_assert( std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value or std::is_same ::value , "incompatible pointer type"); // delegate the call to get_impl_ptr<>() const return get_impl_ptr(static_cast (nullptr)); } /*! @brief get a reference value (implicit) Implicit reference access to the internally stored JSON value. No copies are made. @warning Writing data to the referee of the result yields an undefined state. @tparam ReferenceType reference type; must be a reference to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref number_float_t. Enforced by static assertion. @return reference to the internally stored JSON value if the requested reference type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise @throw std::domain_error in case passed type @a ReferenceType is incompatible with the stored JSON value @complexity Constant. @liveexample{The example shows several calls to `get_ref()`.,get_ref} @since version 1.1.0 */ template ::value, int>::type = 0> ReferenceType get_ref() { // delegate call to get_ref_impl return get_ref_impl (*this); } /*! @brief get a reference value (implicit) @copydoc get_ref() */ template ::value and std::is_const ::type>::value, int>::type = 0> ReferenceType get_ref() const { // delegate call to get_ref_impl return get_ref_impl (*this); } /*! @brief get a value (implicit) Implicit type conversion between the JSON value and a compatible value. The call is realized by calling @ref get() const. @tparam ValueType non-pointer type compatible to the JSON value, for instance `int` for JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for JSON arrays. The character type of @ref string_t as well as an initializer list of this type is excluded to avoid ambiguities as these types implicitly convert to `std::string`. @return copy of the JSON value, converted to type @a ValueType @throw std::domain_error in case passed type @a ValueType is incompatible to JSON, thrown by @ref get() const @complexity Linear in the size of the JSON value. @liveexample{The example below shows several conversions from JSON values to other types. There a few things to note: (1) Floating-point numbers can be converted to integers\, (2) A JSON array can be converted to a standard `std::vector `\, (3) A JSON object can be converted to C++ associative containers such as `std::unordered_map `.,operator__ValueType} @since version 1.0.0 */ template < typename ValueType, typename std::enable_if < not std::is_pointer ::value and not std::is_same ::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same >::value #endif , int >::type = 0 > operator ValueType() const { // delegate the call to get<>() const return get (); } /// @} //////////////////// // element access // //////////////////// /// @name element access /// Access to the JSON value. /// @{ /*! @brief access specified array element with bounds checking Returns a reference to the element at specified location @a idx, with bounds checking. @param[in] idx index of the element to access @return reference to the element at index @a idx @throw std::domain_error if the JSON value is not an array; example: `"cannot use at() with string"` @throw std::out_of_range if the index @a idx is out of range of the array; that is, `idx >= size()`; example: `"array index 7 is out of range"` @complexity Constant. @liveexample{The example below shows how array elements can be read and written using `at()`.,at__size_type} @since version 1.0.0 */ reference at(size_type idx) { // at only works for arrays if (is_array()) { JSON_TRY { return m_value.array->at(idx); } JSON_CATCH (std::out_of_range&) { // create better exception explanation JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range")); } } else { JSON_THROW(std::domain_error("cannot use at() with " + type_name())); } } []
operatorValueType()const
in /src/tinygltf/examples/validator/src/json.hpp:3492
[] void []
default_parse_context::parse_string
in /src/tinygltf/examples/common/picojson.h:878
['input '] bool []
default_parse_context::parse_array_item
in /src/tinygltf/examples/common/picojson.h:886
['input '] bool []
default_parse_context::parse_object_item
in /src/tinygltf/examples/common/picojson.h:897
['input ', 'std::string'] bool []

Sink functions/methods found for CWE22

Target sink Reached by fuzzer Function call path Possible branch blockers
copy [] Path 1
Path 2
N/A